inet6.py revision 2e4998399cbf90a00e4700507cd519f51346e1f2
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 27d7dd2222e18718ea755fe780e8ef422901ba5b0bPhilimport socket 28d7dd2222e18718ea755fe780e8ef422901ba5b0bPhilif not socket.has_ipv6: 29d7dd2222e18718ea755fe780e8ef422901ba5b0bPhil raise socket.error("can't use AF_INET6, IPv6 is disabled") 3081dfaee354bef2beea581a3c83a33c856ade45e5Dirk Lossif not hasattr(socket, "IPPROTO_IPV6"): 3181dfaee354bef2beea581a3c83a33c856ade45e5Dirk Loss # Workaround for http://bugs.python.org/issue6926 3281dfaee354bef2beea581a3c83a33c856ade45e5Dirk Loss socket.IPPROTO_IPV6 = 41 3303f254bf6424098cea56ba24cd5b8099c66a5823Robert Gomulkaif not hasattr(socket, "IPPROTO_IPIP"): 3403f254bf6424098cea56ba24cd5b8099c66a5823Robert Gomulka # Workaround for https://bitbucket.org/secdev/scapy/issue/5119 3503f254bf6424098cea56ba24cd5b8099c66a5823Robert Gomulka socket.IPPROTO_IPIP = 4 36d7dd2222e18718ea755fe780e8ef422901ba5b0bPhil 37d7dd2222e18718ea755fe780e8ef422901ba5b0bPhilfrom scapy.config import conf 38614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.layers.l2 import * 39614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.layers.inet import * 40614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.fields import * 41614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.packet import * 42614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.volatile import * 43614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.sendrecv import sr,sr1,srp1 44614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.as_resolvers import AS_resolver_riswhois 45614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.supersocket import SuperSocket,L3RawSocket 46614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.arch import * 4772461d0c00f182855906e57dcf6223aa9f1d8b31Philfrom scapy.utils6 import * 48c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 49c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 50c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 51c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Helpers ## 52c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 53c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 54c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef get_cls(name, fallback_cls): 55614f54fc4b269030ba2934b6c353fb43de886e04Phil return globals().get(name, fallback_cls) 56c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 57c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 58c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil########################## 59c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil## Neighbor cache stuff ## 60c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil########################## 61c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 62f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Philconf.netcache.new_cache("in6_neighbor", 120) 63c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 64c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef neighsol(addr, src, iface, timeout=1, chainCC=0): 65c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil """ 66c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil Sends an ICMPv6 Neighbor Solicitation message to get the MAC address 67c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil of the neighbor with specified IPv6 address addr. 'src' address is 68c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil used as source of the message. Message is sent on iface. By default, 69c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil timeout waiting for an answer is 1 second. 70c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 71c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil If no answer is gathered, None is returned. Else, the answer is 72c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil returned (ethernet frame). 73c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil """ 74c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 75c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil nsma = in6_getnsma(inet_pton(socket.AF_INET6, addr)) 76c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil d = inet_ntop(socket.AF_INET6, nsma) 77c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil dm = in6_getnsmac(nsma) 78c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil p = Ether(dst=dm)/IPv6(dst=d, src=src, hlim=255) 79c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil p /= ICMPv6ND_NS(tgt=addr) 80c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil p /= ICMPv6NDOptSrcLLAddr(lladdr=get_if_hwaddr(iface)) 81c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil res = srp1(p,type=ETH_P_IPV6, iface=iface, timeout=1, verbose=0, 82c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil chainCC=chainCC) 83c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 84c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return res 85c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 86c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef getmacbyip6(ip6, chainCC=0): 87c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil """ 88c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil Returns the mac address to be used for provided 'ip6' peer. 89c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil neighborCache.get() method is used on instantiated neighbor cache. 90c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil Resolution mechanism is described in associated doc string. 91c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 92c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil (chainCC parameter value ends up being passed to sending function 93c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil used to perform the resolution, if needed) 94c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil """ 95f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil 96f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil if in6_ismaddr(ip6): # Multicast 97f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil mac = in6_getnsmac(inet_pton(socket.AF_INET6, ip6)) 98f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil return mac 99f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil 100f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil iff,a,nh = conf.route6.route(ip6, dev=conf.iface6) 101f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil 102f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil if iff == LOOPBACK_NAME: 103f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil return "ff:ff:ff:ff:ff:ff" 104f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil 105f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil if nh != '::': 106f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil ip6 = nh # Found next hop 107f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil 108f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil mac = conf.netcache.in6_neighbor.get(ip6) 109f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil if mac: 110f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil return mac 111f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil 112f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil res = neighsol(ip6, a, iff, chainCC=chainCC) 113f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil 114f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil if res is not None: 115429082158fc01432c9d5e4a3de775f7a6e07a021Guillaume Valadon if ICMPv6NDOptDstLLAddr in res: 116429082158fc01432c9d5e4a3de775f7a6e07a021Guillaume Valadon mac = res[ICMPv6NDOptDstLLAddr].lladdr 117429082158fc01432c9d5e4a3de775f7a6e07a021Guillaume Valadon else: 118429082158fc01432c9d5e4a3de775f7a6e07a021Guillaume Valadon mac = res.src 119f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil conf.netcache.in6_neighbor[ip6] = mac 120f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil return mac 121f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil 122f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil return None 123c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 124c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 125c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 126c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 127c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil### IPv6 addresses manipulation routines ### 128c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 129c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 130c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 131c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass Net6(Gen): # syntax ex. fec0::/126 132c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil """Generate a list of IPv6s from a network address or a name""" 133c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ipv6" 134c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ipaddress = re.compile(r"^([a-fA-F0-9:]+)(/[1]?[0-3]?[0-9])?$") 135c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 136c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def __init__(self, net): 137c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil self.repr = net 138c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 139c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil tmp = net.split('/')+["128"] 140c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if not self.ipaddress.match(net): 141c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil tmp[0]=socket.getaddrinfo(tmp[0], None, socket.AF_INET6)[0][-1][0] 142c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 143c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil netmask = int(tmp[1]) 14477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil self.net = inet_pton(socket.AF_INET6, tmp[0]) 145c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil self.mask = in6_cidr2mask(netmask) 14677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil self.plen = netmask 147c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 148c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def __iter__(self): 149c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def m8(i): 15077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil if i % 8 == 0: 151c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return i 152c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil tuple = filter(lambda x: m8(x), xrange(8, 129)) 153c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 154c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil a = in6_and(self.net, self.mask) 155c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil tmp = map(lambda x: x, struct.unpack('16B', a)) 156c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 157c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def parse_digit(a, netmask): 158c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil netmask = min(8,max(netmask,0)) 159c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil a = (int(a) & (0xffL<<netmask),(int(a) | (0xffL>>(8-netmask)))+1) 160c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return a 161c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil self.parsed = map(lambda x,y: parse_digit(x,y), tmp, map(lambda x,nm=self.plen: x-nm, tuple)) 162c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 163c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def rec(n, l): 16477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil if n and n % 2 == 0: 16577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil sep = ':' 16677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil else: 167c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil sep = '' 168c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if n == 16: 16977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil return l 170c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil else: 17177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil ll = [] 17277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil for i in xrange(*self.parsed[n]): 17377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil for y in l: 17477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil ll += [y+sep+'%.2x'%i] 17577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil return rec(n+1, ll) 176c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 177c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return iter(rec(0, [''])) 178c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 179c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def __repr__(self): 180c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return "<Net6 %s>" % self.repr 181c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 182c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 183c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 184c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 185c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 186c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 187c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 188c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 189c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil### IPv6 Class ### 190c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 191c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 192c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 193c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IP6Field(Field): 194c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def __init__(self, name, default): 195c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil Field.__init__(self, name, default, "16s") 196c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def h2i(self, pkt, x): 197c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if type(x) is str: 198c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil try: 19977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil x = in6_ptop(x) 200c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil except socket.error: 201c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = Net6(x) 202c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif type(x) is list: 203c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = map(Net6, x) 204c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return x 205c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def i2m(self, pkt, x): 206c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return inet_pton(socket.AF_INET6, x) 207c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def m2i(self, pkt, x): 208c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return inet_ntop(socket.AF_INET6, x) 209c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def any2i(self, pkt, x): 210c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.h2i(pkt,x) 211c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def i2repr(self, pkt, x): 212c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if x is None: 21377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil return self.i2h(pkt,x) 21477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil elif not isinstance(x, Net6) and not type(x) is list: 21577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil if in6_isaddrTeredo(x): # print Teredo info 21677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil server, flag, maddr, mport = teredoAddrExtractInfo(x) 21777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil return "%s [Teredo srv: %s cli: %s:%s]" % (self.i2h(pkt, x), server, maddr,mport) 21877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil elif in6_isaddr6to4(x): # print encapsulated address 219c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil vaddr = in6_6to4ExtractAddr(x) 22077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil return "%s [6to4 GW: %s]" % (self.i2h(pkt, x), vaddr) 22177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil return self.i2h(pkt, x) # No specific information to return 22251db482d4ed62a5eb7b70c0c4f7a3954d41b6165Phil def randval(self): 22351db482d4ed62a5eb7b70c0c4f7a3954d41b6165Phil return RandIP6() 224c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 225c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass SourceIP6Field(IP6Field): 226c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def __init__(self, name, dstname): 227c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IP6Field.__init__(self, name, None) 228c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil self.dstname = dstname 229c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def i2m(self, pkt, x): 230c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if x is None: 231c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil dst=getattr(pkt,self.dstname) 232c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil iff,x,nh = conf.route6.route(dst) 233c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return IP6Field.i2m(self, pkt, x) 234c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def i2h(self, pkt, x): 235c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if x is None: 236c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil dst=getattr(pkt,self.dstname) 237c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if isinstance(dst,Gen): 238c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil r = map(conf.route6.route, dst) 239c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil r.sort() 240c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if r[0] == r[-1]: 241c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x=r[0][1] 242c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil else: 243c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil warning("More than one possible route for %s"%repr(dst)) 244c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return None 245c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil else: 24677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil iff,x,nh = conf.route6.route(dst) 247c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return IP6Field.i2h(self, pkt, x) 248c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 249c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilipv6nh = { 0:"Hop-by-Hop Option Header", 250c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 4:"IP", 251c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 6:"TCP", 252c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 17:"UDP", 253c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 41:"IPv6", 254c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 43:"Routing Header", 255c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 44:"Fragment Header", 256c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 47:"GRE", 257c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 50:"ESP Header", 258c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 51:"AH Header", 259c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 58:"ICMPv6", 260c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 59:"No Next Header", 261c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 60:"Destination Option Header", 2620d49a3d0e63f90e8a46a9221b85ed599fa1b186fsachetmittal 132:"SCTP", 263c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 135:"Mobility Header"} 264c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 265c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilipv6nhcls = { 0: "IPv6ExtHdrHopByHop", 266c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 4: "IP", 267c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 6: "TCP", 268c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 17: "UDP", 269c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 43: "IPv6ExtHdrRouting", 270c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 44: "IPv6ExtHdrFragment", 271c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil #50: "IPv6ExtHrESP", 272c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil #51: "IPv6ExtHdrAH", 27377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil 58: "ICMPv6Unknown", 274c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 59: "Raw", 2755a64a524ad2b2b3e9d6ee03035e1d9aa52aef32fsachetmittal 60: "IPv6ExtHdrDestOpt" } 276c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 277c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IP6ListField(StrField): 278c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil islist = 1 279c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def __init__(self, name, default, count_from=None, length_from=None): 280c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if default is None: 281c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil default = [] 282c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil StrField.__init__(self, name, default) 283c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil self.count_from = count_from 284c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil self.length_from = length_from 285c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 286c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def i2len(self, pkt, i): 287c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return 16*len(i) 288c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 289c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def i2count(self, pkt, i): 290c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if type(i) is list: 291c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return len(i) 292c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return 0 293c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 294c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def getfield(self, pkt, s): 295c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil c = l = None 296c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if self.length_from is not None: 297c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil l = self.length_from(pkt) 298c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif self.count_from is not None: 299c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil c = self.count_from(pkt) 300c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 301c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil lst = [] 302c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ret = "" 303c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil remain = s 304c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if l is not None: 305c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil remain,ret = s[:l],s[l:] 306c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil while remain: 307c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if c is not None: 308c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if c <= 0: 309c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil break 310c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil c -= 1 311c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil addr = inet_ntop(socket.AF_INET6, remain[:16]) 312c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil lst.append(addr) 313c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil remain = remain[16:] 314c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return remain+ret,lst 315c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 316c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def i2m(self, pkt, x): 31777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil s = '' 318c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil for y in x: 319c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil try: 320c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil y = inet_pton(socket.AF_INET6, y) 321c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil except: 322c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil y = socket.getaddrinfo(y, None, socket.AF_INET6)[0][-1][0] 323c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil y = inet_pton(socket.AF_INET6, y) 324c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil s += y 32577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil return s 326c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 327c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def i2repr(self,pkt,x): 328c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil s = [] 32977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil if x == None: 33077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil return "[]" 33177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil for y in x: 33277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil s.append('%s' % y) 333c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return "[ %s ]" % (", ".join(s)) 33477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil 33577132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass _IPv6GuessPayload: 336c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "Dummy class that implements guess_payload_class() for IPv6" 337c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def default_payload_class(self,p): 338b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon if self.nh == 58: # ICMPv6 339c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil t = ord(p[0]) 340b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon if len(p) > 2 and t == 139 or t == 140: # Node Info Query 341c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return _niquery_guesser(p) 342b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon if len(p) >= icmp6typesminhdrlen.get(t, sys.maxint): # Other ICMPv6 messages 343b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon return get_cls(icmp6typescls.get(t,"Raw"), "Raw") 344b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon return Raw 345d5f51f6843ffa1d375e947a5cb03965b5291129dPierre LALET elif self.nh == 135 and len(p) > 3: # Mobile IPv6 346c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return _mip6_mhtype2cls.get(ord(p[2]), MIP6MH_Generic) 34777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil else: 34877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil return get_cls(ipv6nhcls.get(self.nh,"Raw"), "Raw") 349c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 350c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IPv6(_IPv6GuessPayload, Packet, IPTools): 351c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "IPv6" 352c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ BitField("version" , 6 , 4), 353c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil BitField("tc", 0, 8), #TODO: IPv6, ByteField ? 35477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil BitField("fl", 0, 20), 35577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil ShortField("plen", None), 356c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteEnumField("nh", 59, ipv6nh), 357c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("hlim", 64), 358c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil SourceIP6Field("src", "dst"), # dst is for src @ selection 359c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IP6Field("dst", "::1") ] 360614f54fc4b269030ba2934b6c353fb43de886e04Phil 361614f54fc4b269030ba2934b6c353fb43de886e04Phil def route(self): 362614f54fc4b269030ba2934b6c353fb43de886e04Phil dst = self.dst 363614f54fc4b269030ba2934b6c353fb43de886e04Phil if isinstance(dst,Gen): 364614f54fc4b269030ba2934b6c353fb43de886e04Phil dst = iter(dst).next() 365614f54fc4b269030ba2934b6c353fb43de886e04Phil return conf.route6.route(dst) 366614f54fc4b269030ba2934b6c353fb43de886e04Phil 367c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def mysummary(self): 368c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return "%s > %s (%i)" % (self.src,self.dst, self.nh) 369c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 370c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def post_build(self, p, pay): 37177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil p += pay 372c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if self.plen is None: 373c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil l = len(p) - 40 374c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil p = p[:4]+struct.pack("!H", l)+p[6:] 375c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return p 376c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 377c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def extract_padding(self, s): 378c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil l = self.plen 379c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s[:l], s[l:] 380c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 381c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def hashret(self): 382c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if self.nh == 58 and isinstance(self.payload, _ICMPv6): 383c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if self.payload.type < 128: 384c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.payload.payload.hashret() 385c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif (self.payload.type in [133,134,135,136,144,145]): 386c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return struct.pack("B", self.nh)+self.payload.hashret() 387c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 38877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil nh = self.nh 38977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil sd = self.dst 39077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil ss = self.src 391c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if self.nh == 43 and isinstance(self.payload, IPv6ExtHdrRouting): 39277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil # With routing header, the destination is the last 39377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil # address of the IPv6 list if segleft > 0 39477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil nh = self.payload.nh 39577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil try: 39677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil sd = self.addresses[-1] 39777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil except IndexError: 39877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil sd = '::1' 39977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil # TODO: big bug with ICMPv6 error messages as the destination of IPerror6 40077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil # could be anything from the original list ... 40177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil if 1: 40277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil sd = inet_pton(socket.AF_INET6, sd) 40377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil for a in self.addresses: 40477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil a = inet_pton(socket.AF_INET6, a) 40577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil sd = strxor(sd, a) 40677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil sd = inet_ntop(socket.AF_INET6, sd) 407c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 408c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if self.nh == 44 and isinstance(self.payload, IPv6ExtHdrFragment): 409c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil nh = self.payload.nh 410c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 411c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if self.nh == 0 and isinstance(self.payload, IPv6ExtHdrHopByHop): 412c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil nh = self.payload.nh 413c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 414c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if self.nh == 60 and isinstance(self.payload, IPv6ExtHdrDestOpt): 415c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil foundhao = None 416c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil for o in self.payload.options: 417c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if isinstance(o, HAO): 418c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil foundhao = o 419c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if foundhao: 420c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil nh = self.payload.nh # XXX what if another extension follows ? 421c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ss = foundhao.hoa 422c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 423c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if conf.checkIPsrc and conf.checkIPaddr: 424c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil sd = inet_pton(socket.AF_INET6, sd) 425c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ss = inet_pton(socket.AF_INET6, self.src) 426c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return struct.pack("B",nh)+self.payload.hashret() 427c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil else: 428c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return struct.pack("B", nh)+self.payload.hashret() 429c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 430c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def answers(self, other): 431c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if not isinstance(other, IPv6): # self is reply, other is request 432c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return False 433c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if conf.checkIPaddr: 434c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ss = inet_pton(socket.AF_INET6, self.src) 435c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil sd = inet_pton(socket.AF_INET6, self.dst) 436c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil os = inet_pton(socket.AF_INET6, other.src) 437c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil od = inet_pton(socket.AF_INET6, other.dst) 43877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil # request was sent to a multicast address (other.dst) 439c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # Check reply destination addr matches request source addr (i.e 440c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # sd == os) except when reply is multicasted too 441c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # XXX test mcast scope matching ? 442c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if in6_ismaddr(other.dst): 443c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if in6_ismaddr(self.dst): 444c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if ((od == sd) or 445c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil (in6_isaddrllallnodes(self.dst) and in6_isaddrllallservers(other.dst))): 446c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.payload.answers(other.payload) 447c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return False 448c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if (os == sd): 449c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.payload.answers(other.payload) 450c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return False 451c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif (sd != os): # or ss != od): <- removed for ICMP errors 452c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return False 453c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if self.nh == 58 and isinstance(self.payload, _ICMPv6) and self.payload.type < 128: 454c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # ICMPv6 Error message -> generated by IPv6 packet 455c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # Note : at the moment, we jump the ICMPv6 specific class 456c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # to call answers() method of erroneous packet (over 457c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # initial packet). There can be cases where an ICMPv6 error 458c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # class could implement a specific answers method that perform 459c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # a specific task. Currently, don't see any use ... 460c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.payload.payload.answers(other) 461c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif other.nh == 0 and isinstance(other.payload, IPv6ExtHdrHopByHop): 462c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.payload.answers(other.payload.payload) 463c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif other.nh == 44 and isinstance(other.payload, IPv6ExtHdrFragment): 464c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.payload.answers(other.payload.payload) 465c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif other.nh == 43 and isinstance(other.payload, IPv6ExtHdrRouting): 466c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.payload.answers(other.payload.payload) # Buggy if self.payload is a IPv6ExtHdrRouting 467c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif other.nh == 60 and isinstance(other.payload, IPv6ExtHdrDestOpt): 468c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.payload.payload.answers(other.payload.payload) 469c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif self.nh == 60 and isinstance(self.payload, IPv6ExtHdrDestOpt): # BU in reply to BRR, for instance 470c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.payload.payload.answers(other.payload) 471c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil else: 472c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if (self.nh != other.nh): 473c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return False 474c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.payload.answers(other.payload) 475c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 476614f54fc4b269030ba2934b6c353fb43de886e04Phil 477614f54fc4b269030ba2934b6c353fb43de886e04Philconf.neighbor.register_l3(Ether, IPv6, lambda l2,l3: getmacbyip6(l3.dst)) 478614f54fc4b269030ba2934b6c353fb43de886e04Phil 479c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 480c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IPerror6(IPv6): 481c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "IPv6 in ICMPv6" 482c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def answers(self, other): 483c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if not isinstance(other, IPv6): 484c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return False 48577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil sd = inet_pton(socket.AF_INET6, self.dst) 48677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil ss = inet_pton(socket.AF_INET6, self.src) 48777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil od = inet_pton(socket.AF_INET6, other.dst) 48877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil os = inet_pton(socket.AF_INET6, other.src) 489c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 49077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil # Make sure that the ICMPv6 error is related to the packet scapy sent 49177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil if isinstance(self.underlayer, _ICMPv6) and self.underlayer.type < 128: 492c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 493c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # find upper layer for self (possible citation) 494c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil selfup = self.payload 495c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil while selfup is not None and isinstance(selfup, _IPv6ExtHdr): 496c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil selfup = selfup.payload 497c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 498c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # find upper layer for other (initial packet). Also look for RH 499c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil otherup = other.payload 500c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil request_has_rh = False 501c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil while otherup is not None and isinstance(otherup, _IPv6ExtHdr): 502c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if isinstance(otherup, IPv6ExtHdrRouting): 503c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil request_has_rh = True 504c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil otherup = otherup.payload 505c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 50677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil if ((ss == os and sd == od) or # <- Basic case 507c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil (ss == os and request_has_rh)): # <- Request has a RH : 508c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # don't check dst address 509c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 510c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # Let's deal with possible MSS Clamping 511c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if (isinstance(selfup, TCP) and 512c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil isinstance(otherup, TCP) and 513c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil selfup.options != otherup.options): # seems clamped 514c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 515c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # Save fields modified by MSS clamping 516c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil old_otherup_opts = otherup.options 517c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil old_otherup_cksum = otherup.chksum 518c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil old_otherup_dataofs = otherup.dataofs 519c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil old_selfup_opts = selfup.options 520c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil old_selfup_cksum = selfup.chksum 521c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil old_selfup_dataofs = selfup.dataofs 522c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 523c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # Nullify them 524c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil otherup.options = [] 525c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil otherup.chksum = 0 526c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil otherup.dataofs = 0 527c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil selfup.options = [] 528c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil selfup.chksum = 0 529c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil selfup.dataofs = 0 530c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 531c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # Test it and save result 532c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil s1 = str(selfup) 533c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil s2 = str(otherup) 534c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil l = min(len(s1), len(s2)) 535c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil res = s1[:l] == s2[:l] 536c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 537c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # recall saved values 538c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil otherup.options = old_otherup_opts 539c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil otherup.chksum = old_otherup_cksum 540c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil otherup.dataofs = old_otherup_dataofs 541c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil selfup.options = old_selfup_opts 542c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil selfup.chksum = old_selfup_cksum 543c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil selfup.dataofs = old_selfup_dataofs 544c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 545c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return res 546c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 547c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil s1 = str(selfup) 548c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil s2 = str(otherup) 549c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil l = min(len(s1), len(s2)) 550c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s1[:l] == s2[:l] 551c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 552c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return False 553c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 554c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def mysummary(self): 555c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return Packet.mysummary(self) 556c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 557c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 558c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 559c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 560c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil### Upper Layer Checksum computation ### 561c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 562c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 563c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 564c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass PseudoIPv6(Packet): # IPv6 Pseudo-header for checksum computation 565c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "Pseudo IPv6 Header" 566c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ IP6Field("src", "::"), 567c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IP6Field("dst", "::"), 56877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil ShortField("uplen", None), 569c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil BitField("zero", 0, 24), 570c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("nh", 0) ] 571c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 572c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef in6_chksum(nh, u, p): 573c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil """ 574c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil Performs IPv6 Upper Layer checksum computation. Provided parameters are: 575c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 576c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil - 'nh' : value of upper layer protocol 577c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil - 'u' : upper layer instance (TCP, UDP, ICMPv6*, ). Instance must be 578c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil provided with all under layers (IPv6 and all extension headers, 579c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil for example) 580c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil - 'p' : the payload of the upper layer provided as a string 581c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 582c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil Functions operate by filling a pseudo header class instance (PseudoIPv6) 583c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil with 584c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil - Next Header value 585c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil - the address of _final_ destination (if some Routing Header with non 586c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil segleft field is present in underlayer classes, last address is used.) 587c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil - the address of _real_ source (basically the source address of an 588c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IPv6 class instance available in the underlayer or the source address 589c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil in HAO option if some Destination Option header found in underlayer 590c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil includes this option). 591c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil - the length is the length of provided payload string ('p') 592c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil """ 593c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 594c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ph6 = PseudoIPv6() 595c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ph6.nh = nh 596c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil rthdr = 0 597c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil hahdr = 0 598c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil final_dest_addr_found = 0 599c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil while u != None and not isinstance(u, IPv6): 60077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil if (isinstance(u, IPv6ExtHdrRouting) and 60177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil u.segleft != 0 and len(u.addresses) != 0 and 602c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil final_dest_addr_found == 0): 60377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil rthdr = u.addresses[-1] 604c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil final_dest_addr_found = 1 60577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil elif (isinstance(u, IPv6ExtHdrDestOpt) and (len(u.options) == 1) and 606c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil isinstance(u.options[0], HAO)): 607c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil hahdr = u.options[0].hoa 60877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil u = u.underlayer 609c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if u is None: 61077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil warning("No IPv6 underlayer to compute checksum. Leaving null.") 61177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil return 0 61277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil if hahdr: 61377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil ph6.src = hahdr 614c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil else: 615c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ph6.src = u.src 616c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if rthdr: 61777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil ph6.dst = rthdr 618c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil else: 61977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil ph6.dst = u.dst 620c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ph6.uplen = len(p) 621c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ph6s = str(ph6) 622c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return checksum(ph6s+p) 623c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 624c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 625c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 626c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 627c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil### Extension Headers ### 628c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 629c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 630c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 631c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 632c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Inherited by all extension header classes 633c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _IPv6ExtHdr(_IPv6GuessPayload, Packet): 634c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = 'Abstract IPV6 Option Header' 635c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil aliastypes = [IPv6, IPerror6] # TODO ... 636c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 637c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 638c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#################### IPv6 options for Extension Headers ##################### 639c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 640c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_hbhopts = { 0x00: "Pad1", 641c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 0x01: "PadN", 642c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 0x04: "Tunnel Encapsulation Limit", 643c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 0x05: "Router Alert", 644c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 0x06: "Quick-Start", 645c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 0xc2: "Jumbo Payload", 646c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 0xc9: "Home Address Option" } 647c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 648c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _OTypeField(ByteEnumField): 649c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil """ 650c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil Modified BytEnumField that displays information regarding the IPv6 option 651c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil based on its option type value (What should be done by nodes that process 652c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil the option if they do not understand it ...) 653c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 654c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil It is used by Jumbo, Pad1, PadN, RouterAlert, HAO options 655c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil """ 656c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil pol = {0x00: "00: skip", 657c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 0x40: "01: discard", 658c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 0x80: "10: discard+ICMP", 659c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 0xC0: "11: discard+ICMP not mcast"} 660c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 661c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil enroutechange = {0x00: "0: Don't change en-route", 662c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 0x20: "1: May change en-route" } 663c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 664c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def i2repr(self, pkt, x): 665c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil s = self.i2s.get(x, repr(x)) 666c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil polstr = self.pol[(x & 0xC0)] 667c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil enroutechangestr = self.enroutechange[(x & 0x20)] 668c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return "%s [%s, %s]" % (s, polstr, enroutechangestr) 669c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 670c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass HBHOptUnknown(Packet): # IPv6 Hop-By-Hop Option 671c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "Scapy6 Unknown Option" 672c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [_OTypeField("otype", 0x01, _hbhopts), 673c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil FieldLenField("optlen", None, length_of="optdata", fmt="B"), 674c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil StrLenField("optdata", "", 675c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil length_from = lambda pkt: pkt.optlen) ] 676c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def alignment_delta(self, curpos): # By default, no alignment requirement 677c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil """ 678c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil As specified in section 4.2 of RFC 2460, every options has 679c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil an alignment requirement ususally expressed xn+y, meaning 680c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil the Option Type must appear at an integer multiple of x octest 681c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil from the start of the header, plus y octet. 682c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 683c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil That function is provided the current position from the 684c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil start of the header and returns required padding length. 685c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil """ 686c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return 0 687c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 688c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass Pad1(Packet): # IPv6 Hop-By-Hop Option 689c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "Pad1" 690c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ _OTypeField("otype", 0x00, _hbhopts) ] 691c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def alignment_delta(self, curpos): # No alignment requirement 692c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return 0 693c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 694c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass PadN(Packet): # IPv6 Hop-By-Hop Option 695c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "PadN" 696c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [_OTypeField("otype", 0x01, _hbhopts), 697c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil FieldLenField("optlen", None, length_of="optdata", fmt="B"), 698c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil StrLenField("optdata", "", 699c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil length_from = lambda pkt: pkt.optlen)] 700c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def alignment_delta(self, curpos): # No alignment requirement 701c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return 0 702c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 703c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass RouterAlert(Packet): # RFC 2711 - IPv6 Hop-By-Hop Option 704c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "Router Alert" 705c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [_OTypeField("otype", 0x05, _hbhopts), 706c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("optlen", 2), 707c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ShortEnumField("value", None, 708c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil { 0: "Datagram contains a MLD message", 709c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1: "Datagram contains RSVP message", 710c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2: "Datagram contains an Active Network message" }) ] 711c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # TODO : Check IANA has not defined new values for value field of RouterAlertOption 712c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # TODO : now that we have that option, we should do something in MLD class that need it 713c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def alignment_delta(self, curpos): # alignment requirement : 2n+0 714c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = 2 ; y = 0 715c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil delta = x*((curpos - y + x - 1)/x) + y - curpos 716c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return delta 717c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 718c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass Jumbo(Packet): # IPv6 Hop-By-Hop Option 719c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "Jumbo Payload" 720c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [_OTypeField("otype", 0xC2, _hbhopts), 721c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("optlen", 4), 722c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IntField("jumboplen", None) ] 723c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def alignment_delta(self, curpos): # alignment requirement : 4n+2 724c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = 4 ; y = 2 725c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil delta = x*((curpos - y + x - 1)/x) + y - curpos 726c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return delta 727c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 728c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass HAO(Packet): # IPv6 Destination Options Header Option 729c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "Home Address Option" 730c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [_OTypeField("otype", 0xC9, _hbhopts), 731c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("optlen", 16), 732c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IP6Field("hoa", "::") ] 733c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def alignment_delta(self, curpos): # alignment requirement : 8n+6 734c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = 8 ; y = 6 735c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil delta = x*((curpos - y + x - 1)/x) + y - curpos 736c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return delta 737c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 738c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_hbhoptcls = { 0x00: Pad1, 739c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 0x01: PadN, 740c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 0x05: RouterAlert, 741c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 0xC2: Jumbo, 742c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 0xC9: HAO } 743c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 744c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 745c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil######################## Hop-by-Hop Extension Header ######################## 746c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 747c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _HopByHopOptionsField(PacketListField): 748c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def __init__(self, name, default, cls, curpos, count_from=None, length_from=None): 749c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil self.curpos = curpos 750c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil PacketListField.__init__(self, name, default, cls, count_from=count_from, length_from=length_from) 751c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 752c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def i2len(self, pkt, i): 753c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil l = len(self.i2m(pkt, i)) 754c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return l 755c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 756c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def i2count(self, pkt, i): 757c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if type(i) is list: 758c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return len(i) 759c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return 0 760c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 761c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def getfield(self, pkt, s): 762c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil c = l = None 763c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if self.length_from is not None: 764c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil l = self.length_from(pkt) 765c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif self.count_from is not None: 766c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil c = self.count_from(pkt) 767c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 768c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil opt = [] 769c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ret = "" 770c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = s 771c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if l is not None: 772c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x,ret = s[:l],s[l:] 773c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil while x: 774c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if c is not None: 775c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if c <= 0: 776c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil break 777c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil c -= 1 778c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil o = ord(x[0]) # Option type 779c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil cls = self.cls 780c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if _hbhoptcls.has_key(o): 781c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil cls = _hbhoptcls[o] 782c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil try: 783c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil op = cls(x) 784c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil except: 785c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil op = self.cls(x) 786c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil opt.append(op) 7877b3e970663abd72697e17b70aba9943ae0dad404Phil if isinstance(op.payload, conf.raw_layer): 788c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = op.payload.load 789c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil del(op.payload) 790c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil else: 791c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = "" 792c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return x+ret,opt 793c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 794c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def i2m(self, pkt, x): 795c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil autopad = None 796c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil try: 797c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil autopad = getattr(pkt, "autopad") # Hack : 'autopad' phantom field 798c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil except: 799c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil autopad = 1 800c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 801c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if not autopad: 802c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return "".join(map(str, x)) 803c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 804c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil curpos = self.curpos 805c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil s = "" 806c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil for p in x: 807c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil d = p.alignment_delta(curpos) 808c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil curpos += d 809c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if d == 1: 810c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil s += str(Pad1()) 811c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif d != 0: 812c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil s += str(PadN(optdata='\x00'*(d-2))) 813c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil pstr = str(p) 814c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil curpos += len(pstr) 815c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil s += pstr 816c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 817c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # Let's make the class including our option field 818c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # a multiple of 8 octets long 819c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil d = curpos % 8 820c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if d == 0: 821c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s 822c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil d = 8 - d 823c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if d == 1: 824c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil s += str(Pad1()) 825c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif d != 0: 826c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil s += str(PadN(optdata='\x00'*(d-2))) 827c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 828c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s 829c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 830c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def addfield(self, pkt, s, val): 831c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s+self.i2m(pkt, val) 832c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 833c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _PhantomAutoPadField(ByteField): 834c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def addfield(self, pkt, s, val): 835c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s 836c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 837c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def getfield(self, pkt, s): 838c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s, 1 839c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 840c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def i2repr(self, pkt, x): 841c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if x: 842c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return "On" 843c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return "Off" 844c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 845c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 846c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IPv6ExtHdrHopByHop(_IPv6ExtHdr): 847c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "IPv6 Extension Header - Hop-by-Hop Options Header" 848c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("nh", 59, ipv6nh), 849c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil FieldLenField("len", None, length_of="options", fmt="B", 850c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil adjust = lambda pkt,x: (x+2+7)/8 - 1), 851c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil _PhantomAutoPadField("autopad", 1), # autopad activated by default 85277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil _HopByHopOptionsField("options", [], HBHOptUnknown, 2, 853c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil length_from = lambda pkt: (8*(pkt.len+1))-2) ] 854c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil overload_fields = {IPv6: { "nh": 0 }} 855c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 856c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 857c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil######################## Destination Option Header ########################## 858c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 859c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IPv6ExtHdrDestOpt(_IPv6ExtHdr): 860c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "IPv6 Extension Header - Destination Options Header" 861c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("nh", 59, ipv6nh), 862c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil FieldLenField("len", None, length_of="options", fmt="B", 863c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil adjust = lambda pkt,x: (x+2+7)/8 - 1), 864c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil _PhantomAutoPadField("autopad", 1), # autopad activated by default 86577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil _HopByHopOptionsField("options", [], HBHOptUnknown, 2, 866c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil length_from = lambda pkt: (8*(pkt.len+1))-2) ] 867c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil overload_fields = {IPv6: { "nh": 60 }} 868c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 869c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 870c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################# Routing Header ################################ 871c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 872c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IPv6ExtHdrRouting(_IPv6ExtHdr): 873c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "IPv6 Option Header Routing" 874c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("nh", 59, ipv6nh), 875c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil FieldLenField("len", None, count_of="addresses", fmt="B", 876c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil adjust = lambda pkt,x:2*x), # in 8 bytes blocks 877c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("type", 0), 878c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("segleft", None), 879c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil BitField("reserved", 0, 32), # There is meaning in this field ... 88077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil IP6ListField("addresses", [], 881c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil length_from = lambda pkt: 8*pkt.len)] 882c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil overload_fields = {IPv6: { "nh": 43 }} 883c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 884c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def post_build(self, pkt, pay): 885c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if self.segleft is None: 886c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil pkt = pkt[:3]+struct.pack("B", len(self.addresses))+pkt[4:] 887c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return _IPv6ExtHdr.post_build(self, pkt, pay) 888c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 889c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil########################### Fragmentation Header ############################ 890c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 89177132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass IPv6ExtHdrFragment(_IPv6ExtHdr): 892c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "IPv6 Extension Header - Fragmentation header" 893c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("nh", 59, ipv6nh), 894c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil BitField("res1", 0, 8), 89577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil BitField("offset", 0, 13), 89677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil BitField("res2", 0, 2), 89777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil BitField("m", 0, 1), 89877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil IntField("id", None) ] 899c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil overload_fields = {IPv6: { "nh": 44 }} 900c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 901c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 902c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef defragment6(pktlist): 903c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil """ 904c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil Performs defragmentation of a list of IPv6 packets. Packets are reordered. 905c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil Crap is dropped. What lacks is completed by 'X' characters. 906c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil """ 907c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 908c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil l = filter(lambda x: IPv6ExtHdrFragment in x, pktlist) # remove non fragments 909c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if not l: 910c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return [] 911c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 912c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil id = l[0][IPv6ExtHdrFragment].id 913c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 914c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil llen = len(l) 915c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil l = filter(lambda x: x[IPv6ExtHdrFragment].id == id, l) 916c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if len(l) != llen: 917c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil warning("defragment6: some fragmented packets have been removed from list") 918c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil llen = len(l) 919c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 920c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # reorder fragments 921c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil i = 0 922c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil res = [] 923c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil while l: 924c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil min_pos = 0 925c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil min_offset = l[0][IPv6ExtHdrFragment].offset 926c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil for p in l: 927c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil cur_offset = p[IPv6ExtHdrFragment].offset 928c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if cur_offset < min_offset: 929c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil min_pos = 0 930c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil min_offset = cur_offset 931c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil res.append(l[min_pos]) 932c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil del(l[min_pos]) 933c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 934c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # regenerate the fragmentable part 935c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fragmentable = "" 936c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil for p in res: 937c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil q=p[IPv6ExtHdrFragment] 938c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil offset = 8*q.offset 939c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if offset != len(fragmentable): 940c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil warning("Expected an offset of %d. Found %d. Padding with XXXX" % (len(fragmentable), offset)) 941c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fragmentable += "X"*(offset - len(fragmentable)) 942c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fragmentable += str(q.payload) 943c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 944c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # Regenerate the unfragmentable part. 945c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil q = res[0] 946c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil nh = q[IPv6ExtHdrFragment].nh 947c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil q[IPv6ExtHdrFragment].underlayer.nh = nh 948c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil q[IPv6ExtHdrFragment].underlayer.payload = None 9497b3e970663abd72697e17b70aba9943ae0dad404Phil q /= conf.raw_layer(load=fragmentable) 950c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 951c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return IPv6(str(q)) 952c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 953c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 954c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef fragment6(pkt, fragSize): 955c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil """ 956c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil Performs fragmentation of an IPv6 packet. Provided packet ('pkt') must already 957c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil contain an IPv6ExtHdrFragment() class. 'fragSize' argument is the expected 958c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil maximum size of fragments (MTU). The list of packets is returned. 959c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 960c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil If packet does not contain an IPv6ExtHdrFragment class, it is returned in 961c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil result list. 962c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil """ 963c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 964c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil pkt = pkt.copy() 965c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 966c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if not IPv6ExtHdrFragment in pkt: 967c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # TODO : automatically add a fragment before upper Layer 968c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # at the moment, we do nothing and return initial packet 969c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # as single element of a list 970c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return [pkt] 971c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 97295776ce795664e3f0703cf245792dc6e9d8d6ca6Guillaume Valadon # If the payload is bigger than 65535, a Jumbo payload must be used, as 97395776ce795664e3f0703cf245792dc6e9d8d6ca6Guillaume Valadon # an IPv6 packet can't be bigger than 65535 bytes. 974d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon if len(str(pkt[IPv6ExtHdrFragment])) > 65535: 97595776ce795664e3f0703cf245792dc6e9d8d6ca6Guillaume Valadon warning("An IPv6 packet can'be bigger than 65535, please use a Jumbo payload.") 97695776ce795664e3f0703cf245792dc6e9d8d6ca6Guillaume Valadon return [] 977d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon 978d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon s = str(pkt) # for instantiation to get upper layer checksum right 979d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon 980d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon if len(s) <= fragSize: 981d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon return [pkt] 982d5e4a897680762663fd14993a4f2c9691675ec29Guillaume Valadon 983c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # Fragmentable part : fake IPv6 for Fragmentable part length computation 984c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fragPart = pkt[IPv6ExtHdrFragment].payload 985c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil tmp = str(IPv6(src="::1", dst="::1")/fragPart) 986c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fragPartLen = len(tmp) - 40 # basic IPv6 header length 987c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fragPartStr = s[-fragPartLen:] 988c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 989c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # Grab Next Header for use in Fragment Header 990c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil nh = IPv6(tmp[:40]).nh 991c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 992c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # Keep fragment header 993c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fragHeader = pkt[IPv6ExtHdrFragment] 994c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fragHeader.payload = None # detach payload 995c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 996c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # Unfragmentable Part 997c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil unfragPartLen = len(s) - fragPartLen - 8 998c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil unfragPart = pkt 999c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil pkt[IPv6ExtHdrFragment].underlayer.payload = None # detach payload 1000c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1001c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # Cut the fragmentable part to fit fragSize. Inner fragments have 1002c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # a length that is an integer multiple of 8 octets. last Frag MTU 1003c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # can be anything below MTU 1004c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil lastFragSize = fragSize - unfragPartLen - 8 1005c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil innerFragSize = lastFragSize - (lastFragSize % 8) 1006c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1007c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if lastFragSize <= 0 or innerFragSize == 0: 1008c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil warning("Provided fragment size value is too low. " + 1009c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil "Should be more than %d" % (unfragPartLen + 8)) 1010c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return [unfragPart/fragHeader/fragPart] 1011c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1012c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil remain = fragPartStr 1013c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil res = [] 1014c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fragOffset = 0 # offset, incremeted during creation 1015c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fragId = random.randint(0,0xffffffff) # random id ... 1016c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if fragHeader.id is not None: # ... except id provided by user 1017c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fragId = fragHeader.id 1018c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fragHeader.m = 1 1019c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fragHeader.id = fragId 1020c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fragHeader.nh = nh 1021c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1022c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # Main loop : cut, fit to FRAGSIZEs, fragOffset, Id ... 1023c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil while True: 1024c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if (len(remain) > lastFragSize): 1025c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil tmp = remain[:innerFragSize] 1026c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil remain = remain[innerFragSize:] 1027c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fragHeader.offset = fragOffset # update offset 1028c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fragOffset += (innerFragSize / 8) # compute new one 1029c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if IPv6 in unfragPart: 1030c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil unfragPart[IPv6].plen = None 10317b3e970663abd72697e17b70aba9943ae0dad404Phil tempo = unfragPart/fragHeader/conf.raw_layer(load=tmp) 1032c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil res.append(tempo) 1033c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil else: 1034c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fragHeader.offset = fragOffset # update offSet 1035c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fragHeader.m = 0 1036c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if IPv6 in unfragPart: 1037c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil unfragPart[IPv6].plen = None 10387b3e970663abd72697e17b70aba9943ae0dad404Phil tempo = unfragPart/fragHeader/conf.raw_layer(load=remain) 1039c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil res.append(tempo) 1040c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil break 1041c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return res 1042c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1043c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1044c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################### AH Header ################################### 1045c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1046c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# class _AHFieldLenField(FieldLenField): 1047c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# def getfield(self, pkt, s): 1048c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# l = getattr(pkt, self.fld) 1049c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# l = (l*8)-self.shift 1050c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# i = self.m2i(pkt, s[:l]) 1051c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# return s[l:],i 1052c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1053c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# class _AHICVStrLenField(StrLenField): 1054c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# def i2len(self, pkt, x): 1055c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1056c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1057c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1058c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# class IPv6ExtHdrAH(_IPv6ExtHdr): 1059c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# name = "IPv6 Extension Header - AH" 1060c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# fields_desc = [ ByteEnumField("nh", 59, ipv6nh), 1061c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# _AHFieldLenField("len", None, "icv"), 1062c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# ShortField("res", 0), 1063c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# IntField("spi", 0), 1064c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# IntField("sn", 0), 1065c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# _AHICVStrLenField("icv", None, "len", shift=2) ] 1066c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# overload_fields = {IPv6: { "nh": 51 }} 1067c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1068c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# def post_build(self, pkt, pay): 1069c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# if self.len is None: 1070c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# pkt = pkt[0]+struct.pack("!B", 2*len(self.addresses))+pkt[2:] 1071c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# if self.segleft is None: 1072c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# pkt = pkt[:3]+struct.pack("!B", len(self.addresses))+pkt[4:] 1073c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# return _IPv6ExtHdr.post_build(self, pkt, pay) 1074c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1075c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1076c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################### ESP Header ################################## 1077c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1078c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# class IPv6ExtHdrESP(_IPv6extHdr): 1079c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# name = "IPv6 Extension Header - ESP" 1080c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# fields_desc = [ IntField("spi", 0), 1081c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# IntField("sn", 0), 1082c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# # there is things to extract from IKE work 1083c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# ] 1084c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# overloads_fields = {IPv6: { "nh": 50 }} 1085c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1086c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1087c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1088c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 1089c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 1090c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil### ICMPv6* Classes ### 1091c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 1092c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 1093c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1094c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilicmp6typescls = { 1: "ICMPv6DestUnreach", 1095c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2: "ICMPv6PacketTooBig", 1096c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 3: "ICMPv6TimeExceeded", 1097c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 4: "ICMPv6ParamProblem", 1098c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 128: "ICMPv6EchoRequest", 1099c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 129: "ICMPv6EchoReply", 1100c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 130: "ICMPv6MLQuery", 1101c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 131: "ICMPv6MLReport", 1102c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 132: "ICMPv6MLDone", 1103c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 133: "ICMPv6ND_RS", 1104c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 134: "ICMPv6ND_RA", 1105c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 135: "ICMPv6ND_NS", 1106c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 136: "ICMPv6ND_NA", 1107c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 137: "ICMPv6ND_Redirect", 1108c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil #138: Do Me - RFC 2894 - Seems painful 1109c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 139: "ICMPv6NIQuery", 1110c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 140: "ICMPv6NIReply", 1111c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 141: "ICMPv6ND_INDSol", 1112c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 142: "ICMPv6ND_INDAdv", 1113c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil #143: Do Me - RFC 3810 111477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil 144: "ICMPv6HAADRequest", 111577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil 145: "ICMPv6HAADReply", 111677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil 146: "ICMPv6MPSol", 111777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil 147: "ICMPv6MPAdv", 1118c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil #148: Do Me - SEND related - RFC 3971 1119c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil #149: Do Me - SEND related - RFC 3971 1120c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 151: "ICMPv6MRD_Advertisement", 1121c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 152: "ICMPv6MRD_Solicitation", 1122c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 153: "ICMPv6MRD_Termination", 112377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil } 1124c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1125b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadonicmp6typesminhdrlen = { 1: 8, 1126b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon 2: 8, 1127b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon 3: 8, 1128b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon 4: 8, 1129b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon 128: 8, 1130b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon 129: 8, 1131b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon 130: 24, 1132b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon 131: 24, 1133b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon 132: 24, 1134b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon 133: 8, 1135b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon 134: 16, 1136b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon 135: 24, 1137b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon 136: 24, 1138b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon 137: 40, 1139b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon #139: 1140b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon #140 1141b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon 141: 8, 1142b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon 142: 8, 1143b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon 144: 8, 1144b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon 145: 8, 1145b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon 146: 8, 1146b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon 147: 8, 1147b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon 151: 8, 1148b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon 152: 4, 1149b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon 153: 4 1150b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon } 1151b48efefaba1304096cd3eb0c52cc7b01ef93fb2dGuillaume Valadon 1152c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilicmp6types = { 1 : "Destination unreachable", 1153c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2 : "Packet too big", 115477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil 3 : "Time exceeded", 1155c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 4 : "Parameter problem", 1156c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 100 : "Private Experimentation", 1157c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 101 : "Private Experimentation", 1158c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 128 : "Echo Request", 1159c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 129 : "Echo Reply", 1160c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 130 : "MLD Query", 116177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil 131 : "MLD Report", 116277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil 132 : "MLD Done", 116377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil 133 : "Router Solicitation", 116477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil 134 : "Router Advertisement", 116577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil 135 : "Neighbor Solicitation", 116677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil 136 : "Neighbor Advertisement", 116777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil 137 : "Redirect Message", 116877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil 138 : "Router Renumbering", 116977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil 139 : "ICMP Node Information Query", 117077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil 140 : "ICMP Node Information Response", 117177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil 141 : "Inverse Neighbor Discovery Solicitation Message", 117277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil 142 : "Inverse Neighbor Discovery Advertisement Message", 117377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil 143 : "Version 2 Multicast Listener Report", 117477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil 144 : "Home Agent Address Discovery Request Message", 117577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil 145 : "Home Agent Address Discovery Reply Message", 117677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil 146 : "Mobile Prefix Solicitation", 117777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil 147 : "Mobile Prefix Advertisement", 117877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil 148 : "Certification Path Solicitation", 117977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil 149 : "Certification Path Advertisement", 1180c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 151 : "Multicast Router Advertisement", 1181c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 152 : "Multicast Router Solicitation", 1182c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 153 : "Multicast Router Termination", 1183c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 200 : "Private Experimentation", 1184c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 201 : "Private Experimentation" } 1185c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1186c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1187c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6(Packet): 1188c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 dummy class" 1189c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil overload_fields = {IPv6: {"nh": 58}} 1190c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def post_build(self, p, pay): 119177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil p += pay 1192c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if self.cksum == None: 119377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil chksum = in6_chksum(58, self.underlayer, p) 119477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil p = p[:2]+struct.pack("!H", chksum)+p[4:] 119577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil return p 1196c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1197c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def hashret(self): 1198c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.payload.hashret() 1199c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1200c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def answers(self, other): 1201c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # isinstance(self.underlayer, _IPv6ExtHdr) may introduce a bug ... 120277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil if (isinstance(self.underlayer, IPerror6) or 1203c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil isinstance(self.underlayer, _IPv6ExtHdr) and 1204c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil isinstance(other, _ICMPv6)): 120577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil if not ((self.type == other.type) and 120677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil (self.code == other.code)): 120777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil return 0 120877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil return 1 120977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil return 0 1210c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1211c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1212c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6Error(_ICMPv6): 1213c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 errors dummy class" 1214c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def guess_payload_class(self,p): 121577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil return IPerror6 1216c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1217c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6Unknown(_ICMPv6): 1218c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "Scapy6 ICMPv6 fallback class" 1219c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("type",1, icmp6types), 1220c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("code",0), 1221c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None), 1222c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil StrField("msgbody", "")] 1223c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1224c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1225c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil################################## RFC 2460 ################################# 1226c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1227c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6DestUnreach(_ICMPv6Error): 1228c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Destination Unreachable" 1229c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("type",1, icmp6types), 1230c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteEnumField("code",0, { 0: "No route to destination", 1231c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1: "Communication with destination administratively prohibited", 1232c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2: "Beyond scope of source address", 1233c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 3: "Address unreachable", 1234c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 4: "Port unreachable" }), 1235c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None), 1236c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XIntField("unused",0x00000000)] 1237c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1238c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6PacketTooBig(_ICMPv6Error): 1239c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Packet Too Big" 1240c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("type",2, icmp6types), 1241c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("code",0), 1242c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None), 1243c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IntField("mtu",1280)] 1244c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1245c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6TimeExceeded(_ICMPv6Error): 1246c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Time Exceeded" 1247c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("type",3, icmp6types), 1248b77e3cb7813eb79374d688dab2e1c4382cc6c6e3Guillaume Valadon ByteEnumField("code",0, { 0: "hop limit exceeded in transit", 1249b77e3cb7813eb79374d688dab2e1c4382cc6c6e3Guillaume Valadon 1: "fragment reassembly time exceeded"}), 1250c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None), 1251c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XIntField("unused",0x00000000)] 1252c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1253c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# The default pointer value is set to the next header field of 1254c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# the encapsulated IPv6 packet 1255c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ParamProblem(_ICMPv6Error): 1256c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Parameter Problem" 1257c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("type",4, icmp6types), 1258c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteEnumField("code",0, {0: "erroneous header field encountered", 1259c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1: "unrecognized Next Header type encountered", 1260c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2: "unrecognized IPv6 option encountered"}), 1261c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None), 1262c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IntField("ptr",6)] 1263c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1264c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6EchoRequest(_ICMPv6): 1265c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Echo Request" 1266c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("type", 128, icmp6types), 1267c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("code", 0), 1268c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None), 1269c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("id",0), 1270c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("seq",0), 1271c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil StrField("data", "")] 1272c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def mysummary(self): 1273c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.sprintf("%name% (id: %id% seq: %seq%)") 1274c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def hashret(self): 1275c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return struct.pack("HH",self.id,self.seq)+self.payload.hashret() 1276c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1277c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1278c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6EchoReply(ICMPv6EchoRequest): 1279c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Echo Reply" 1280c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil type = 129 1281c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def answers(self, other): 1282c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # We could match data content between request and reply. 1283c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return (isinstance(other, ICMPv6EchoRequest) and 1284c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil self.id == other.id and self.seq == other.seq and 1285c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil self.data == other.data) 1286c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1287c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1288c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############ ICMPv6 Multicast Listener Discovery (RFC3810) ################## 1289c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1290c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# tous les messages MLD sont emis avec une adresse source lien-locale 1291c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# -> Y veiller dans le post_build si aucune n'est specifiee 1292c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# La valeur de Hop-Limit doit etre de 1 1293c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# "and an IPv6 Router Alert option in a Hop-by-Hop Options 1294c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# header. (The router alert option is necessary to cause routers to 1295c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# examine MLD messages sent to multicast addresses in which the router 1296c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# itself has no interest" 1297c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6ML(_ICMPv6): 1298c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("type", 130, icmp6types), 1299c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("code", 0), 1300c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None), 1301c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ShortField("mrd", 0), 1302c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ShortField("reserved", 0), 1303b77e3cb7813eb79374d688dab2e1c4382cc6c6e3Guillaume Valadon IP6Field("mladdr","::")] 1304c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1305c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# general queries are sent to the link-scope all-nodes multicast 1306c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# address ff02::1, with a multicast address field of 0 and a MRD of 1307c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [Query Response Interval] 1308c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Default value for mladdr is set to 0 for a General Query, and 1309c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# overloaded by the user for a Multicast Address specific query 1310c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO : See what we can do to automatically include a Router Alert 1311c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Option in a Destination Option Header. 1312c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MLQuery(_ICMPv6ML): # RFC 2710 1313c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "MLD - Multicast Listener Query" 1314c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil type = 130 1315c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil mrd = 10000 1316c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil mladdr = "::" # 10s for mrd 1317e1d0631a37e4326084e0fa2a9cb9f6466667d9e8Guillaume Valadon overload_fields = {IPv6: { "dst": "ff02::1", "hlim": 1, "nh": 58 }} 1318c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def hashret(self): 1319c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if self.mladdr != "::": 1320c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return struct.pack("HH",self.mladdr)+self.payload.hashret() 1321c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil else: 1322c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.payload.hashret() 1323c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1324c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1325c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO : See what we can do to automatically include a Router Alert 1326c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Option in a Destination Option Header. 1327c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MLReport(_ICMPv6ML): # RFC 2710 1328c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "MLD - Multicast Listener Report" 1329c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil type = 131 1330e1d0631a37e4326084e0fa2a9cb9f6466667d9e8Guillaume Valadon overload_fields = {IPv6: {"hlim": 1, "nh": 58}} 1331c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # implementer le hashret et le answers 1332c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1333c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# When a node ceases to listen to a multicast address on an interface, 1334c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# it SHOULD send a single Done message to the link-scope all-routers 1335c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# multicast address (FF02::2), carrying in its multicast address field 1336c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# the address to which it is ceasing to listen 1337c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO : See what we can do to automatically include a Router Alert 1338c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Option in a Destination Option Header. 1339c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MLDone(_ICMPv6ML): # RFC 2710 1340c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "MLD - Multicast Listener Done" 1341c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil type = 132 1342f9727001edc936020f47735a7653bbe1d2533026Guillaume Valadon overload_fields = {IPv6: { "dst": "ff02::2", "hlim": 1, "nh": 58}} 1343c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1344c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1345c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil########## ICMPv6 MRD - Multicast Router Discovery (RFC 4286) ############### 1346c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1347c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO: 1348c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - 04/09/06 troglocan : find a way to automatically add a router alert 1349c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# option for all MRD packets. This could be done in a specific 1350c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# way when IPv6 is the under layer with some specific keyword 1351c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# like 'exthdr'. This would allow to keep compatibility with 1352c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# providing IPv6 fields to be overloaded in fields_desc. 1353c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# 1354c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# At the moment, if user inserts an IPv6 Router alert option 1355c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# none of the IPv6 default values of IPv6 layer will be set. 1356c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1357c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MRD_Advertisement(_ICMPv6): 1358c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Multicast Router Discovery Advertisement" 1359c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ByteEnumField("type", 151, icmp6types), 1360c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("advinter", 20), 1361c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None), 1362c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ShortField("queryint", 0), 1363c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ShortField("robustness", 0)] 1364c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil overload_fields = {IPv6: { "nh": 58, "hlim": 1, "dst": "ff02::2"}} 1365c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # IPv6 Router Alert requires manual inclusion 1366c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def extract_padding(self, s): 1367c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s[:8], s[8:] 1368c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1369c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MRD_Solicitation(_ICMPv6): 1370c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Multicast Router Discovery Solicitation" 1371c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ByteEnumField("type", 152, icmp6types), 1372c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("res", 0), 1373c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None) ] 1374c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil overload_fields = {IPv6: { "nh": 58, "hlim": 1, "dst": "ff02::2"}} 1375c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # IPv6 Router Alert requires manual inclusion 1376c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def extract_padding(self, s): 1377c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s[:4], s[4:] 1378c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1379c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MRD_Termination(_ICMPv6): 1380c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Multicast Router Discovery Termination" 1381c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ByteEnumField("type", 153, icmp6types), 1382c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("res", 0), 1383c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None) ] 1384c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil overload_fields = {IPv6: { "nh": 58, "hlim": 1, "dst": "ff02::6A"}} 1385c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # IPv6 Router Alert requires manual inclusion 1386c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def extract_padding(self, s): 1387c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s[:4], s[4:] 1388c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1389c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1390c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil################### ICMPv6 Neighbor Discovery (RFC 2461) #################### 1391c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1392c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilicmp6ndopts = { 1: "Source Link-Layer Address", 1393c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2: "Target Link-Layer Address", 1394c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 3: "Prefix Information", 1395c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 4: "Redirected Header", 1396c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 5: "MTU", 1397c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 6: "NBMA Shortcut Limit Option", # RFC2491 1398c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 7: "Advertisement Interval Option", 1399c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 8: "Home Agent Information Option", 1400c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 9: "Source Address List", 1401c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 10: "Target Address List", 1402c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 11: "CGA Option", # RFC 3971 1403c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 12: "RSA Signature Option", # RFC 3971 1404c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 13: "Timestamp Option", # RFC 3971 1405c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 14: "Nonce option", # RFC 3971 1406c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 15: "Trust Anchor Option", # RFC 3971 1407c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 16: "Certificate Option", # RFC 3971 1408c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 17: "IP Address Option", # RFC 4068 1409c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 18: "New Router Prefix Information Option", # RFC 4068 1410c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 19: "Link-layer Address Option", # RFC 4068 1411c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 20: "Neighbor Advertisement Acknowledgement Option", 1412c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 21: "CARD Request Option", # RFC 4065/4066/4067 1413c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 22: "CARD Reply Option", # RFC 4065/4066/4067 1414c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 23: "MAP Option", # RFC 4140 1415c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 24: "Route Information Option", # RFC 4191 1416c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 25: "Recusive DNS Server Option", 1417c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 26: "IPv6 Router Advertisement Flags Option" 1418c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil } 1419c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1420c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilicmp6ndoptscls = { 1: "ICMPv6NDOptSrcLLAddr", 1421c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2: "ICMPv6NDOptDstLLAddr", 1422c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 3: "ICMPv6NDOptPrefixInfo", 1423c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 4: "ICMPv6NDOptRedirectedHdr", 1424c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 5: "ICMPv6NDOptMTU", 1425c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 6: "ICMPv6NDOptShortcutLimit", 1426c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 7: "ICMPv6NDOptAdvInterval", 1427c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 8: "ICMPv6NDOptHAInfo", 1428c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 9: "ICMPv6NDOptSrcAddrList", 1429c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 10: "ICMPv6NDOptTgtAddrList", 1430c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil #11: Do Me, 1431c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil #12: Do Me, 1432c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil #13: Do Me, 1433c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil #14: Do Me, 1434c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil #15: Do Me, 1435c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil #16: Do Me, 1436c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 17: "ICMPv6NDOptIPAddr", 1437c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 18: "ICMPv6NDOptNewRtrPrefix", 1438c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 19: "ICMPv6NDOptLLA", 1439c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil #18: Do Me, 1440c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil #19: Do Me, 1441c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil #20: Do Me, 1442c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil #21: Do Me, 1443c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil #22: Do Me, 1444c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 23: "ICMPv6NDOptMAP", 1445c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 24: "ICMPv6NDOptRouteInfo", 1446c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 25: "ICMPv6NDOptRDNSS", 14472e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon 26: "ICMPv6NDOptEFA", 14482e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon 31: "ICMPv6NDOptDNSSL" 1449c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil } 1450c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1451c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6NDGuessPayload: 1452c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "Dummy ND class that implements guess_payload_class()" 1453c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def guess_payload_class(self,p): 1454c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if len(p) > 1: 1455c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return get_cls(icmp6ndoptscls.get(ord(p[0]),"Raw"), "Raw") # s/Raw/ICMPv6NDOptUnknown/g ? 1456c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1457c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1458c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Beginning of ICMPv6 Neighbor Discovery Options. 1459c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1460c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptUnknown(_ICMPv6NDGuessPayload, Packet): 1461c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Neighbor Discovery Option - Scapy Unimplemented" 1462c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteField("type",None), 1463c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil FieldLenField("len",None,length_of="data",fmt="B", 1464c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil adjust = lambda pkt,x: x+2), 1465c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil StrLenField("data","", 1466c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil length_from = lambda pkt: pkt.len-2) ] 1467c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1468c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# NOTE: len includes type and len field. Expressed in unit of 8 bytes 1469c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO: Revoir le coup du ETHER_ANY 1470c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptSrcLLAddr(_ICMPv6NDGuessPayload, Packet): 1471c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Neighbor Discovery Option - Source Link-Layer Address" 1472c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteField("type", 1), 1473c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("len", 1), 1474c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil MACField("lladdr", ETHER_ANY) ] 147577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil def mysummary(self): 1476c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.sprintf("%name% %lladdr%") 1477c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1478c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptDstLLAddr(ICMPv6NDOptSrcLLAddr): 1479c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Neighbor Discovery Option - Destination Link-Layer Address" 1480c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil type = 2 1481c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1482c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptPrefixInfo(_ICMPv6NDGuessPayload, Packet): 1483c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Neighbor Discovery Option - Prefix Information" 1484c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteField("type",3), 1485c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("len",4), 1486c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("prefixlen",None), 1487c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil BitField("L",1,1), 1488c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil BitField("A",1,1), 1489c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil BitField("R",0,1), 1490c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil BitField("res1",0,5), 1491c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XIntField("validlifetime",0xffffffffL), 1492c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XIntField("preferredlifetime",0xffffffffL), 1493c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XIntField("res2",0x00000000), 1494c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IP6Field("prefix","::") ] 149577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil def mysummary(self): 1496c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.sprintf("%name% %prefix%") 1497c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1498c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO: We should also limit the size of included packet to something 1499c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# like (initiallen - 40 - 2) 1500c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass TruncPktLenField(PacketLenField): 1501c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1502c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def __init__(self, name, default, cls, cur_shift, length_from=None, shift=0): 1503c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil PacketLenField.__init__(self, name, default, cls, length_from=length_from) 1504c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil self.cur_shift = cur_shift 1505c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1506c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def getfield(self, pkt, s): 1507c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil l = self.length_from(pkt) 1508c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil i = self.m2i(pkt, s[:l]) 1509c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s[l:],i 15104e957e091da2c111732db403e6db503f4b383157Jochen Bartl 1511c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def m2i(self, pkt, m): 15124e957e091da2c111732db403e6db503f4b383157Jochen Bartl s = None 1513c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil try: # It can happen we have sth shorter than 40 bytes 1514c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil s = self.cls(m) 1515c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil except: 15167b3e970663abd72697e17b70aba9943ae0dad404Phil return conf.raw_layer(m) 1517c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s 1518c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1519c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def i2m(self, pkt, x): 1520c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil s = str(x) 1521c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil l = len(s) 1522c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil r = (l + self.cur_shift) % 8 15234e957e091da2c111732db403e6db503f4b383157Jochen Bartl l = l - r 1524c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s[:l] 1525c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1526c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def i2len(self, pkt, i): 1527c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return len(self.i2m(pkt, i)) 1528c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 15294e957e091da2c111732db403e6db503f4b383157Jochen Bartl 1530c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Faire un post_build pour le recalcul de la taille (en multiple de 8 octets) 1531c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptRedirectedHdr(_ICMPv6NDGuessPayload, Packet): 1532c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Neighbor Discovery Option - Redirected Header" 1533c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteField("type",4), 1534c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil FieldLenField("len", None, length_of="pkt", fmt="B", 15354e957e091da2c111732db403e6db503f4b383157Jochen Bartl adjust = lambda pkt,x:(x+8)/8), 1536b5d49cd73a38b87d2a62a74452d3cb0932e6aa7bJochen Bartl StrFixedLenField("res", "\x00"*6, 6), 15374e957e091da2c111732db403e6db503f4b383157Jochen Bartl TruncPktLenField("pkt", "", IPv6, 8, 15384e957e091da2c111732db403e6db503f4b383157Jochen Bartl length_from = lambda pkt: 8*pkt.len-8) ] 1539c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1540c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# See which value should be used for default MTU instead of 1280 1541c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptMTU(_ICMPv6NDGuessPayload, Packet): 1542c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Neighbor Discovery Option - MTU" 1543c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteField("type",5), 1544c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("len",1), 1545c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("res",0), 1546c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IntField("mtu",1280)] 1547c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1548c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptShortcutLimit(_ICMPv6NDGuessPayload, Packet): # RFC 2491 1549c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Neighbor Discovery Option - NBMA Shortcut Limit" 1550c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteField("type", 6), 1551c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("len", 1), 1552c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("shortcutlim", 40), # XXX 1553c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("res1", 0), 1554c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IntField("res2", 0) ] 1555c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1556c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptAdvInterval(_ICMPv6NDGuessPayload, Packet): 1557c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Neighbor Discovery - Interval Advertisement" 1558c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteField("type",7), 1559c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("len",1), 1560c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ShortField("res", 0), 1561c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IntField("advint", 0) ] 156277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil def mysummary(self): 1563c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.sprintf("%name% %advint% milliseconds") 1564c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 156577132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass ICMPv6NDOptHAInfo(_ICMPv6NDGuessPayload, Packet): 1566c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Neighbor Discovery - Home Agent Information" 1567c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteField("type",8), 1568c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("len",1), 1569c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ShortField("res", 0), 1570c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ShortField("pref", 0), 1571c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ShortField("lifetime", 1)] 157277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil def mysummary(self): 1573c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.sprintf("%name% %pref% %lifetime% seconds") 1574c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1575c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# type 9 : See ICMPv6NDOptSrcAddrList class below in IND (RFC 3122) support 1576c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1577c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# type 10 : See ICMPv6NDOptTgtAddrList class below in IND (RFC 3122) support 1578c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 157977132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass ICMPv6NDOptIPAddr(_ICMPv6NDGuessPayload, Packet): # RFC 4068 1580c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Neighbor Discovery - IP Address Option (FH for MIPv6)" 1581c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteField("type",17), 1582c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("len", 3), 1583c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteEnumField("optcode", 1, {1: "Old Care-Of Address", 1584c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2: "New Care-Of Address", 1585c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 3: "NAR's IP address" }), 1586c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("plen", 64), 1587c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IntField("res", 0), 1588c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IP6Field("addr", "::") ] 1589c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1590c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptNewRtrPrefix(_ICMPv6NDGuessPayload, Packet): # RFC 4068 1591c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Neighbor Discovery - New Router Prefix Information Option (FH for MIPv6)" 1592c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteField("type",18), 1593c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("len", 3), 1594c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("optcode", 0), 1595c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("plen", 64), 1596c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IntField("res", 0), 1597c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IP6Field("prefix", "::") ] 1598c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1599c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_rfc4068_lla_optcode = {0: "Wildcard requesting resolution for all nearby AP", 1600c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1: "LLA for the new AP", 1601c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2: "LLA of the MN", 1602c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 3: "LLA of the NAR", 1603c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 4: "LLA of the src of TrSolPr or PrRtAdv msg", 1604c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 5: "AP identified by LLA belongs to current iface of router", 1605c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 6: "No preifx info available for AP identified by the LLA", 1606c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 7: "No fast handovers support for AP identified by the LLA" } 1607c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 160877132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass ICMPv6NDOptLLA(_ICMPv6NDGuessPayload, Packet): # RFC 4068 1609c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Neighbor Discovery - Link-Layer Address (LLA) Option (FH for MIPv6)" 1610c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteField("type", 19), 1611c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("len", 1), 1612c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteEnumField("optcode", 0, _rfc4068_lla_optcode), 1613c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil MACField("lla", ETHER_ANY) ] # We only support ethernet 1614c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 161577132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass ICMPv6NDOptMAP(_ICMPv6NDGuessPayload, Packet): # RFC 4140 1616c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Neighbor Discovery - MAP Option" 1617c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteField("type", 23), 1618c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("len", 3), 1619c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil BitField("dist", 1, 4), 1620c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil BitField("pref", 15, 4), # highest availability 1621c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil BitField("R", 1, 1), 1622c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil BitField("res", 0, 7), 1623c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IntField("validlifetime", 0xffffffff), 1624c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IP6Field("addr", "::") ] 1625c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1626c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1627c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IP6PrefixField(IP6Field): 1628c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def __init__(self, name, default): 1629c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IP6Field.__init__(self, name, default) 1630c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil self.length_from = lambda pkt: 8*(pkt.len - 1) 1631c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1632c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def addfield(self, pkt, s, val): 1633c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s + self.i2m(pkt, val) 1634c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1635c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def getfield(self, pkt, s): 1636c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil l = self.length_from(pkt) 1637c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil p = s[:l] 1638c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if l < 16: 1639c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil p += '\x00'*(16-l) 1640c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s[l:], self.m2i(pkt,p) 1641c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1642c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def i2len(self, pkt, x): 1643c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return len(self.i2m(pkt, x)) 1644c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1645c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def i2m(self, pkt, x): 1646c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil l = pkt.len 1647c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1648c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if x is None: 1649c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = "::" 1650c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if l is None: 1651c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil l = 1 1652c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = inet_pton(socket.AF_INET6, x) 1653c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1654c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if l is None: 1655c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return x 1656c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if l in [0, 1]: 1657c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return "" 1658c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if l in [2, 3]: 1659c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return x[:8*(l-1)] 1660c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1661c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return x + '\x00'*8*(l-3) 1662c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1663c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptRouteInfo(_ICMPv6NDGuessPayload, Packet): # RFC 4191 1664c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Neighbor Discovery Option - Route Information Option" 1665c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteField("type",24), 1666c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil FieldLenField("len", None, length_of="prefix", fmt="B", 1667c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil adjust = lambda pkt,x: x/8 + 1), 1668c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("plen", None), 1669c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil BitField("res1",0,3), 1670c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil BitField("prf",0,2), 1671c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil BitField("res2",0,3), 1672c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IntField("rtlifetime", 0xffffffff), 1673c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IP6PrefixField("prefix", None) ] 1674c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1675c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptRDNSS(_ICMPv6NDGuessPayload, Packet): # RFC 5006 1676c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Neighbor Discovery Option - Recursive DNS Server Option" 1677c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteField("type", 25), 1678c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil FieldLenField("len", None, count_of="dns", fmt="B", 1679c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil adjust = lambda pkt,x: 2*x+1), 1680c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ShortField("res", None), 1681c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IntField("lifetime", 0xffffffff), 1682c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IP6ListField("dns", [], 1683c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil length_from = lambda pkt: 8*(pkt.len-1)) ] 1684c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1685c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptEFA(_ICMPv6NDGuessPayload, Packet): # RFC 5175 (prev. 5075) 1686c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Neighbor Discovery Option - Expanded Flags Option" 1687c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteField("type", 26), 1688c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("len", 1), 1689c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil BitField("res", 0, 48) ] 1690c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 16912e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadonfrom scapy.layers.dhcp6 import DomainNameListField 16922e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadonclass ICMPv6NDOptDNSSL(_ICMPv6NDGuessPayload, Packet): # RFC 6106 16932e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon name = "ICMPv6 Neighbor Discovery Option - DNS Search List Option" 16942e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon fields_desc = [ ByteField("type", 31), 16952e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon FieldLenField("len", None, count_of="searchlist", fmt="B", 16962e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon adjust=lambda pkt, x: 1+ len(pkt.searchlist)), 16972e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon ShortField("res", None), 16982e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon IntField("lifetime", 0xffffffff), 16992e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon DomainNameListField("searchlist", [], 17002e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon length_from=lambda pkt: 8*pkt.len -8, 17012e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon padded=True) 17022e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon ] 17032e4998399cbf90a00e4700507cd519f51346e1f2Guillaume Valadon 1704c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# End of ICMPv6 Neighbor Discovery Options. 1705c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1706c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_RS(_ICMPv6NDGuessPayload, _ICMPv6): 1707c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Neighbor Discovery - Router Solicitation" 1708c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("type", 133, icmp6types), 1709c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("code",0), 1710c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None), 1711c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IntField("res",0) ] 1712c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil overload_fields = {IPv6: { "nh": 58, "dst": "ff02::2", "hlim": 255 }} 1713c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1714c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_RA(_ICMPv6NDGuessPayload, _ICMPv6): 1715c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Neighbor Discovery - Router Advertisement" 1716c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("type", 134, icmp6types), 1717c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("code",0), 1718c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None), 1719c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("chlim",0), 1720c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil BitField("M",0,1), 1721c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil BitField("O",0,1), 1722c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil BitField("H",0,1), 1723c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil BitEnumField("prf",1,2, { 0: "Medium (default)", 1724c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1: "High", 1725c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2: "Reserved", 1726c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 3: "Low" } ), # RFC 4191 1727c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil BitField("P",0,1), 1728c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil BitField("res",0,2), 1729c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ShortField("routerlifetime",1800), 1730c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IntField("reachabletime",0), 1731c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IntField("retranstimer",0) ] 1732c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }} 1733c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1734c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def answers(self, other): 1735c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return isinstance(other, ICMPv6ND_RS) 1736c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1737c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_NS(_ICMPv6NDGuessPayload, _ICMPv6, Packet): 1738c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Neighbor Discovery - Neighbor Solicitation" 1739c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("type",135, icmp6types), 1740c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("code",0), 1741c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None), 17426695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon IntField("res", 0), 1743c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IP6Field("tgt","::") ] 1744c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }} 1745c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1746c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def mysummary(self): 1747c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.sprintf("%name% (tgt: %tgt%)") 1748c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1749c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def hashret(self): 1750c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.tgt+self.payload.hashret() 1751c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 17526695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadonclass ICMPv6ND_NA(_ICMPv6NDGuessPayload, _ICMPv6, Packet): 1753c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Neighbor Discovery - Neighbor Advertisement" 17546695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon fields_desc = [ ByteEnumField("type",136, icmp6types), 17556695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon ByteField("code",0), 17566695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon XShortField("cksum", None), 17576695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon BitField("R",1,1), 17586695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon BitField("S",0,1), 17596695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon BitField("O",1,1), 17606695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon XBitField("res",0,29), 17616695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon IP6Field("tgt","::") ] 17626695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }} 17636695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon 17646695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon def mysummary(self): 17656695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon return self.sprintf("%name% (tgt: %tgt%)") 17666695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon 17676695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon def hashret(self): 17686695b89afb63d30f9a8c2e424ba64765e5d699e5Guillaume Valadon return self.tgt+self.payload.hashret() 1769c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1770c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def answers(self, other): 177177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil return isinstance(other, ICMPv6ND_NS) and self.tgt == other.tgt 1772c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1773c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# associated possible options : target link-layer option, Redirected header 1774c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_Redirect(_ICMPv6NDGuessPayload, _ICMPv6, Packet): 1775c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Neighbor Discovery - Redirect" 1776c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("type",137, icmp6types), 1777c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("code",0), 1778c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None), 1779c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XIntField("res",0), 1780c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IP6Field("tgt","::"), 1781c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IP6Field("dst","::") ] 1782c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }} 1783c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1784c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1785c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1786c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil################ ICMPv6 Inverse Neighbor Discovery (RFC 3122) ############### 1787c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1788c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptSrcAddrList(_ICMPv6NDGuessPayload, Packet): 1789c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Inverse Neighbor Discovery Option - Source Address List" 1790c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteField("type",9), 1791c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil FieldLenField("len", None, count_of="addrlist", fmt="B", 1792c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil adjust = lambda pkt,x: 2*x+1), 1793c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil StrFixedLenField("res", "\x00"*6, 6), 1794c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IP6ListField("addrlist", [], 1795c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil length_from = lambda pkt: 8*(pkt.len-1)) ] 1796c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1797c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptTgtAddrList(ICMPv6NDOptSrcAddrList): 1798c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Inverse Neighbor Discovery Option - Target Address List" 1799c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil type = 10 1800c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1801c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1802c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# RFC3122 1803c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Options requises : source lladdr et target lladdr 1804c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Autres options valides : source address list, MTU 1805c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - Comme precise dans le document, il serait bien de prendre l'adresse L2 1806c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# demandee dans l'option requise target lladdr et l'utiliser au niveau 1807c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# de l'adresse destination ethernet si aucune adresse n'est precisee 1808c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - ca semble pas forcement pratique si l'utilisateur doit preciser toutes 1809c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# les options. 1810c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Ether() must use the target lladdr as destination 1811c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_INDSol(_ICMPv6NDGuessPayload, _ICMPv6): 1812c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Inverse Neighbor Discovery Solicitation" 1813c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("type",141, icmp6types), 1814c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("code",0), 1815c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum",None), 1816c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XIntField("reserved",0) ] 1817c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }} 1818c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1819c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Options requises : target lladdr, target address list 1820c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Autres options valides : MTU 1821c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_INDAdv(_ICMPv6NDGuessPayload, _ICMPv6): 1822c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Inverse Neighbor Discovery Advertisement" 1823c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("type",142, icmp6types), 1824c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("code",0), 1825c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum",None), 1826c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XIntField("reserved",0) ] 1827c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }} 1828c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1829c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1830c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################### 1831c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# ICMPv6 Node Information Queries (RFC 4620) 1832c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################### 1833c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1834c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Add automatic destination address computation using computeNIGroupAddr 1835c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# in IPv6 class (Scapy6 modification when integrated) if : 1836c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - it is not provided 1837c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - upper layer is ICMPv6NIQueryName() with a valid value 1838c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Try to be liberal in what we accept as internal values for _explicit_ 1839c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# DNS elements provided by users. Any string should be considered 1840c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# valid and kept like it has been provided. At the moment, i2repr() will 1841c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# crash on many inputs 1842c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Do the documentation 1843c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Add regression tests 1844c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Perform test against real machines (NOOP reply is proof of implementation). 1845c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Check if there are differences between different stacks. Among *BSD, 1846c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# with others. 1847c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Deal with flags in a consistent way. 1848c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Implement compression in names2dnsrepr() and decompresiion in 1849c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# dnsrepr2names(). Should be deactivable. 1850c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1851c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilicmp6_niqtypes = { 0: "NOOP", 1852c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2: "Node Name", 1853c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 3: "IPv6 Address", 1854c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 4: "IPv4 Address" } 1855c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1856c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1857c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6NIHashret: 1858c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def hashret(self): 1859c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.nonce 1860c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1861c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6NIAnswers: 1862c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def answers(self, other): 1863c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.nonce == other.nonce 1864c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1865c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Buggy; always returns the same value during a session 1866c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NonceField(StrFixedLenField): 1867c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def __init__(self, name, default=None): 1868c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil StrFixedLenField.__init__(self, name, default, 8) 1869c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if default is None: 1870c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil self.default = self.randval() 1871c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1872c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Compute the NI group Address. Can take a FQDN as input parameter 1873c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef computeNIGroupAddr(name): 1874c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil import md5 1875c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = name.lower().split(".")[0] 1876c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil record = chr(len(name))+name 1877c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil h = md5.new(record) 1878c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil h = h.digest() 1879c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil addr = "ff02::2:%2x%2x:%2x%2x" % struct.unpack("BBBB", h[:4]) 1880c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return addr 1881c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1882c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1883c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Here is the deal. First, that protocol is a piece of shit. Then, we 1884c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# provide 4 classes for the different kinds of Requests (one for every 1885c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# valid qtype: NOOP, Node Name, IPv6@, IPv4@). They all share the same 1886c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# data field class that is made to be smart by guessing the specifc 1887c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# type of value provided : 1888c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# 1889c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - IPv6 if acceptable for inet_pton(AF_INET6, ): code is set to 0, 1890c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# if not overriden by user 1891c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - IPv4 if acceptable for inet_pton(AF_INET, ): code is set to 2, 1892c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# if not overriden 1893c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - Name in the other cases: code is set to 0, if not overriden by user 1894c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# 1895c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Internal storage, is not only the value, but the a pair providing 1896c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# the type and the value (1 is IPv6@, 1 is Name or string, 2 is IPv4@) 1897c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# 1898c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Note : I merged getfield() and m2i(). m2i() should not be called 1899c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# directly anyway. Same remark for addfield() and i2m() 1900c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# 1901c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# -- arno 1902c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1903c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# "The type of information present in the Data field of a query is 1904c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# declared by the ICMP Code, whereas the type of information in a 1905c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Reply is determined by the Qtype" 1906c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1907c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef names2dnsrepr(x): 1908c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil """ 1909c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil Take as input a list of DNS names or a single DNS name 1910c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil and encode it in DNS format (with possible compression) 1911c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil If a string that is already a DNS name in DNS format 1912c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil is passed, it is returned unmodified. Result is a string. 1913c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil !!! At the moment, compression is not implemented !!! 1914c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil """ 1915c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1916c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if type(x) is str: 1917c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if x and x[-1] == '\x00': # stupid heuristic 1918c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return x 1919c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = [x] 1920c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1921c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil res = [] 1922c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil for n in x: 1923c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil termin = "\x00" 1924c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if n.count('.') == 0: # single-component gets one more 1925c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil termin += '\x00' 1926c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil n = "".join(map(lambda y: chr(len(y))+y, n.split("."))) + termin 1927c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil res.append(n) 1928c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return "".join(res) 1929c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1930c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1931c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef dnsrepr2names(x): 1932c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil """ 1933c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil Take as input a DNS encoded string (possibly compressed) 1934c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil and returns a list of DNS names contained in it. 1935c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil If provided string is already in printable format 1936c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil (does not end with a null character, a one element list 1937c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil is returned). Result is a list. 1938c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil """ 1939c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil res = [] 1940c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil cur = "" 1941c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil while x: 1942c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil l = ord(x[0]) 1943c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = x[1:] 1944c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if l == 0: 1945c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if cur and cur[-1] == '.': 1946c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil cur = cur[:-1] 1947c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil res.append(cur) 1948c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil cur = "" 1949c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if x and ord(x[0]) == 0: # single component 1950c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = x[1:] 1951c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil continue 1952c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if l & 0xc0: # XXX TODO : work on that -- arno 1953c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil raise Exception("DNS message can't be compressed at this point!") 1954c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil else: 1955c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil cur += x[:l]+"." 1956c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = x[l:] 1957c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return res 1958c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1959c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1960c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NIQueryDataField(StrField): 1961c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def __init__(self, name, default): 1962c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil StrField.__init__(self, name, default) 1963c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1964c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def i2h(self, pkt, x): 1965c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if x is None: 1966c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return x 1967c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil t,val = x 1968c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if t == 1: 1969c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil val = dnsrepr2names(val)[0] 1970c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return val 1971c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1972c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def h2i(self, pkt, x): 1973c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if x is tuple and type(x[0]) is int: 1974c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return x 1975c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1976c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil val = None 1977c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil try: # Try IPv6 1978c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil inet_pton(socket.AF_INET6, x) 1979c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil val = (0, x) 1980c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil except: 1981c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil try: # Try IPv4 1982c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil inet_pton(socket.AF_INET, x) 1983c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil val = (2, x) 1984c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil except: # Try DNS 1985c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if x is None: 1986c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = "" 1987c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = names2dnsrepr(x) 1988c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil val = (1, x) 1989c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return val 1990c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1991c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def i2repr(self, pkt, x): 1992c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil t,val = x 1993c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if t == 1: # DNS Name 1994c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # we don't use dnsrepr2names() to deal with 1995c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # possible weird data extracted info 1996c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil res = [] 1997c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil weird = None 1998c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil while val: 1999c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil l = ord(val[0]) 2000c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil val = val[1:] 2001c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if l == 0: 2002c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if (len(res) > 1 and val): # fqdn with data behind 2003c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil weird = val 2004c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif len(val) > 1: # single label with data behind 2005c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil weird = val[1:] 2006c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil break 2007c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil res.append(val[:l]+".") 2008c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil val = val[l:] 2009c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil tmp = "".join(res) 2010c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if tmp and tmp[-1] == '.': 2011c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil tmp = tmp[:-1] 2012c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return tmp 2013c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return repr(val) 2014c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2015c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def getfield(self, pkt, s): 2016c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil qtype = getattr(pkt, "qtype") 2017c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if qtype == 0: # NOOP 2018c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s, (0, "") 2019c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil else: 2020c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil code = getattr(pkt, "code") 2021c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if code == 0: # IPv6 Addr 2022c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s[16:], (0, inet_ntop(socket.AF_INET6, s[:16])) 2023c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif code == 2: # IPv4 Addr 2024c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s[4:], (2, inet_ntop(socket.AF_INET, s[:4])) 2025c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil else: # Name or Unknown 2026c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return "", (1, s) 2027c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2028c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def addfield(self, pkt, s, val): 2029c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if ((type(val) is tuple and val[1] is None) or 2030c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil val is None): 2031c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil val = (1, "") 2032c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil t = val[0] 2033c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if t == 1: 2034c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s + val[1] 2035c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif t == 0: 2036c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s + inet_pton(socket.AF_INET6, val[1]) 2037c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil else: 2038c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s + inet_pton(socket.AF_INET, val[1]) 2039c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2040c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NIQueryCodeField(ByteEnumField): 2041c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def i2m(self, pkt, x): 2042c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if x is None: 2043c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil d = pkt.getfieldval("data") 2044c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if d is None: 2045c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return 1 2046c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif d[0] == 0: # IPv6 address 2047c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return 0 2048c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif d[0] == 1: # Name 2049c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return 1 2050c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif d[0] == 2: # IPv4 address 2051c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return 2 2052c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil else: 2053c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return 1 2054c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return x 2055c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2056c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2057c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_niquery_code = {0: "IPv6 Query", 1: "Name Query", 2: "IPv4 Query"} 2058c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2059c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#_niquery_flags = { 2: "All unicast addresses", 4: "IPv4 addresses", 206077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil# 8: "Link-local addresses", 16: "Site-local addresses", 2061c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# 32: "Global addresses" } 2062c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2063c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# "This NI type has no defined flags and never has a Data Field". Used 2064c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# to know if the destination is up and implements NI protocol. 2065c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIQueryNOOP(_ICMPv6NIHashret, _ICMPv6): 2066c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Node Information Query - NOOP Query" 2067c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("type", 139, icmp6types), 2068c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil NIQueryCodeField("code", None, _niquery_code), 2069c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None), 2070c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ShortEnumField("qtype", 0, icmp6_niqtypes), 207177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil BitField("unused", 0, 10), 2072c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil FlagsField("flags", 0, 6, "TACLSG"), 207377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil NonceField("nonce", None), 2074c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil NIQueryDataField("data", None) ] 2075c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2076c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIQueryName(ICMPv6NIQueryNOOP): 2077c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Node Information Query - IPv6 Name Query" 2078c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil qtype = 2 2079c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2080c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# We ask for the IPv6 address of the peer 2081c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIQueryIPv6(ICMPv6NIQueryNOOP): 2082c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Node Information Query - IPv6 Address Query" 2083c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil qtype = 3 2084c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil flags = 0x3E 2085c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2086c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIQueryIPv4(ICMPv6NIQueryNOOP): 2087c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Node Information Query - IPv4 Address Query" 2088c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil qtype = 4 2089c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2090c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_nireply_code = { 0: "Successful Reply", 2091c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1: "Response Refusal", 2092c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 3: "Unknown query type" } 2093c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2094c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_nireply_flags = { 1: "Reply set incomplete", 2095c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2: "All unicast addresses", 2096c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 4: "IPv4 addresses", 2097c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 8: "Link-local addresses", 2098c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 16: "Site-local addresses", 2099c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 32: "Global addresses" } 2100c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2101c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Internal repr is one of those : 2102c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# (0, "some string") : unknow qtype value are mapped to that one 2103c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# (3, [ (ttl, ip6), ... ]) 2104c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# (4, [ (ttl, ip4), ... ]) 2105c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# (2, [ttl, dns_names]) : dns_names is one string that contains 2106c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# all the DNS names. Internally it is kept ready to be sent 2107c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# (undissected). i2repr() decode it for user. This is to 2108c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# make build after dissection bijective. 2109c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# 2110c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# I also merged getfield() and m2i(), and addfield() and i2m(). 2111c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NIReplyDataField(StrField): 2112c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2113c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def i2h(self, pkt, x): 2114c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if x is None: 2115c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return x 2116c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil t,val = x 2117c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if t == 2: 2118c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ttl, dnsnames = val 2119c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil val = [ttl] + dnsrepr2names(dnsnames) 2120c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return val 2121c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2122c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def h2i(self, pkt, x): 2123c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil qtype = 0 # We will decode it as string if not 2124c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # overridden through 'qtype' in pkt 2125c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2126c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # No user hint, let's use 'qtype' value for that purpose 2127c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if type(x) is not tuple: 2128c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if pkt is not None: 2129c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil qtype = getattr(pkt, "qtype") 2130c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil else: 2131c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil qtype = x[0] 2132c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = x[1] 2133c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2134c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # From that point on, x is the value (second element of the tuple) 2135c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2136c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if qtype == 2: # DNS name 2137c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if type(x) is str: # listify the string 2138c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = [x] 2139c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if type(x) is list and x and type(x[0]) is not int: # ttl was omitted : use 0 2140c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = [0] + x 2141c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ttl = x[0] 2142c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil names = x[1:] 2143c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return (2, [ttl, names2dnsrepr(names)]) 2144c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2145c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif qtype in [3, 4]: # IPv4 or IPv6 addr 2146c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if type(x) is str: 2147c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = [x] # User directly provided an IP, instead of list 2148c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2149c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # List elements are not tuples, user probably 2150c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # omitted ttl value : we will use 0 instead 2151c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def addttl(x): 2152c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if type(x) is str: 2153c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return (0, x) 2154c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return x 2155c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2156c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return (qtype, map(addttl, x)) 2157c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2158c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return (qtype, x) 2159c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2160c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2161c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def addfield(self, pkt, s, val): 2162c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil t,tmp = val 2163c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if tmp is None: 2164c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil tmp = "" 2165c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if t == 2: 2166c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ttl,dnsstr = tmp 2167c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s+ struct.pack("!I", ttl) + dnsstr 2168c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif t == 3: 2169c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s + "".join(map(lambda (x,y): struct.pack("!I", x)+inet_pton(socket.AF_INET6, y), tmp)) 2170c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif t == 4: 2171c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s + "".join(map(lambda (x,y): struct.pack("!I", x)+inet_pton(socket.AF_INET, y), tmp)) 2172c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil else: 2173c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s + tmp 2174c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2175c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def getfield(self, pkt, s): 2176c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil code = getattr(pkt, "code") 2177c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if code != 0: 2178c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s, (0, "") 2179c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2180c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil qtype = getattr(pkt, "qtype") 2181c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if qtype == 0: # NOOP 2182c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s, (0, "") 2183c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2184c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif qtype == 2: 2185c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if len(s) < 4: 2186c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s, (0, "") 2187c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ttl = struct.unpack("!I", s[:4])[0] 2188c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return "", (2, [ttl, s[4:]]) 2189c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2190c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif qtype == 3: # IPv6 addresses with TTLs 2191c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # XXX TODO : get the real length 2192c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil res = [] 2193c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil while len(s) >= 20: # 4 + 16 2194c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ttl = struct.unpack("!I", s[:4])[0] 2195c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ip = inet_ntop(socket.AF_INET6, s[4:20]) 2196c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil res.append((ttl, ip)) 2197c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil s = s[20:] 2198c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s, (3, res) 2199c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2200c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif qtype == 4: # IPv4 addresses with TTLs 2201c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # XXX TODO : get the real length 2202c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil res = [] 2203c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil while len(s) >= 8: # 4 + 4 2204c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ttl = struct.unpack("!I", s[:4])[0] 2205c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ip = inet_ntop(socket.AF_INET, s[4:8]) 2206c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil res.append((ttl, ip)) 2207c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil s = s[8:] 2208c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s, (4, res) 2209c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil else: 2210c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # XXX TODO : implement me and deal with real length 2211c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return "", (0, s) 2212c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2213c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def i2repr(self, pkt, x): 2214c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if x is None: 2215c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return "[]" 2216c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2217c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if type(x) is tuple and len(x) == 2: 2218c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil t, val = x 2219c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if t == 2: # DNS names 2220c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ttl,l = val 2221c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil l = dnsrepr2names(l) 2222c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return "ttl:%d %s" % (ttl, ", ".join(l)) 2223c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif t == 3 or t == 4: 2224c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return "[ %s ]" % (", ".join(map(lambda (x,y): "(%d, %s)" % (x, y), val))) 2225c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return repr(val) 2226c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return repr(x) # XXX should not happen 2227c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2228c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# By default, sent responses have code set to 0 (successful) 2229c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIReplyNOOP(_ICMPv6NIAnswers, _ICMPv6NIHashret, _ICMPv6): 2230c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Node Information Reply - NOOP Reply" 2231c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("type", 140, icmp6types), 2232c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteEnumField("code", 0, _nireply_code), 2233c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None), 2234c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ShortEnumField("qtype", 0, icmp6_niqtypes), 223577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil BitField("unused", 0, 10), 2236c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil FlagsField("flags", 0, 6, "TACLSG"), 223777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil NonceField("nonce", None), 2238c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil NIReplyDataField("data", None)] 2239c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2240c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIReplyName(ICMPv6NIReplyNOOP): 2241c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Node Information Reply - Node Names" 2242c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil qtype = 2 2243c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2244c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIReplyIPv6(ICMPv6NIReplyNOOP): 2245c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Node Information Reply - IPv6 addresses" 2246c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil qtype = 3 2247c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2248c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIReplyIPv4(ICMPv6NIReplyNOOP): 2249c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Node Information Reply - IPv4 addresses" 2250c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil qtype = 4 2251c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2252c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIReplyRefuse(ICMPv6NIReplyNOOP): 2253c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Node Information Reply - Responder refuses to supply answer" 2254c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil code = 1 2255c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2256c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIReplyUnknown(ICMPv6NIReplyNOOP): 2257c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "ICMPv6 Node Information Reply - Qtype unknown to the responder" 2258c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil code = 2 2259c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2260c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2261c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef _niquery_guesser(p): 22627b3e970663abd72697e17b70aba9943ae0dad404Phil cls = conf.raw_layer 2263c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil type = ord(p[0]) 2264c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if type == 139: # Node Info Query specific stuff 2265c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if len(p) > 6: 2266c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil qtype, = struct.unpack("!H", p[4:6]) 2267c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil cls = { 0: ICMPv6NIQueryNOOP, 2268c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2: ICMPv6NIQueryName, 2269c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 3: ICMPv6NIQueryIPv6, 22707b3e970663abd72697e17b70aba9943ae0dad404Phil 4: ICMPv6NIQueryIPv4 }.get(qtype, conf.raw_layer) 2271c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif type == 140: # Node Info Reply specific stuff 2272c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil code = ord(p[1]) 2273c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if code == 0: 2274c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if len(p) > 6: 2275c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil qtype, = struct.unpack("!H", p[4:6]) 2276c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil cls = { 2: ICMPv6NIReplyName, 2277c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 3: ICMPv6NIReplyIPv6, 2278c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 4: ICMPv6NIReplyIPv4 }.get(qtype, ICMPv6NIReplyNOOP) 2279c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif code == 1: 2280c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil cls = ICMPv6NIReplyRefuse 2281c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif code == 2: 2282c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil cls = ICMPv6NIReplyUnknown 2283c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return cls 2284c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2285c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2286c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 2287c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 2288c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil### Mobile IPv6 (RFC 3775) and Nemo (RFC 3963) ### 2289c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 2290c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 2291c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2292c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Mobile IPv6 ICMPv6 related classes 2293c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2294c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6HAADRequest(_ICMPv6): 2295c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = 'ICMPv6 Home Agent Address Discovery Request' 2296c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("type", 144, icmp6types), 2297c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("code", 0), 2298c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None), 2299c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("id", None), 2300c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil BitEnumField("R", 1, 1, {1: 'MR'}), 2301c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XBitField("res", 0, 15) ] 2302c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def hashret(self): 2303c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return struct.pack("!H",self.id)+self.payload.hashret() 2304c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2305c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6HAADReply(_ICMPv6): 2306c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = 'ICMPv6 Home Agent Address Discovery Reply' 2307c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("type", 145, icmp6types), 2308c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("code", 0), 2309c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None), 2310c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("id", None), 2311c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil BitEnumField("R", 1, 1, {1: 'MR'}), 2312c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XBitField("res", 0, 15), 2313c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IP6ListField('addresses', None) ] 2314c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def hashret(self): 2315c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return struct.pack("!H",self.id)+self.payload.hashret() 2316c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2317c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def answers(self, other): 2318c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if not isinstance(other, ICMPv6HAADRequest): 2319c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return 0 2320c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.id == other.id 2321c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2322c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MPSol(_ICMPv6): 2323c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = 'ICMPv6 Mobile Prefix Solicitation' 2324c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("type", 146, icmp6types), 2325c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("code", 0), 2326c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None), 2327c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("id", None), 2328c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("res", 0) ] 2329c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def _hashret(self): 2330c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return struct.pack("!H",self.id) 2331c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2332c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MPAdv(_ICMPv6NDGuessPayload, _ICMPv6): 2333c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = 'ICMPv6 Mobile Prefix Advertisement' 2334c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("type", 147, icmp6types), 2335c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("code", 0), 2336c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None), 2337c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("id", None), 2338c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil BitEnumField("flags", 2, 2, {2: 'M', 1:'O'}), 2339c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XBitField("res", 0, 14) ] 2340c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def hashret(self): 2341c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return struct.pack("!H",self.id) 2342c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2343c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def answers(self, other): 2344c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return isinstance(other, ICMPv6MPSol) 2345c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2346c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Mobile IPv6 Options classes 2347c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2348c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2349c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_mobopttypes = { 2: "Binding Refresh Advice", 2350c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 3: "Alternate Care-of Address", 2351c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 4: "Nonce Indices", 2352c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 5: "Binding Authorization Data", 2353c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 6: "Mobile Network Prefix (RFC3963)", 2354c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 7: "Link-Layer Address (RFC4068)", 2355c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 8: "Mobile Node Identifier (RFC4283)", 2356c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 9: "Mobility Message Authentication (RFC4285)", 2357c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 10: "Replay Protection (RFC4285)", 2358c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 11: "CGA Parameters Request (RFC4866)", 2359c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 12: "CGA Parameters (RFC4866)", 2360c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 13: "Signature (RFC4866)", 2361c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 14: "Home Keygen Token (RFC4866)", 2362c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 15: "Care-of Test Init (RFC4866)", 2363c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 16: "Care-of Test (RFC4866)" } 2364c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2365c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2366c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _MIP6OptAlign: 2367c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil """ Mobile IPv6 options have alignment requirements of the form x*n+y. 2368c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil This class is inherited by all MIPv6 options to help in computing the 2369c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil required Padding for that option, i.e. the need for a Pad1 or PadN 2370c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil option before it. They only need to provide x and y as class 2371c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil parameters. (x=0 and y=0 are used when no alignment is required)""" 2372c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def alignment_delta(self, curpos): 2373c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = self.x ; y = self.y 2374c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if x == 0 and y ==0: 2375c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return 0 2376c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil delta = x*((curpos - y + x - 1)/x) + y - curpos 2377c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return delta 2378c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2379c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2380c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptBRAdvice(_MIP6OptAlign, Packet): 2381c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = 'Mobile IPv6 Option - Binding Refresh Advice' 2382c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField('otype', 2, _mobopttypes), 2383c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField('olen', 2), 2384c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ShortField('rinter', 0) ] 2385c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = 2 ; y = 0# alignment requirement: 2n 2386c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2387c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptAltCoA(_MIP6OptAlign, Packet): 2388c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = 'MIPv6 Option - Alternate Care-of Address' 2389c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField('otype', 3, _mobopttypes), 2390c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField('olen', 16), 2391c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IP6Field("acoa", "::") ] 2392c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = 8 ; y = 6 # alignment requirement: 8n+6 2393c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 239477132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass MIP6OptNonceIndices(_MIP6OptAlign, Packet): 2395c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = 'MIPv6 Option - Nonce Indices' 2396c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField('otype', 4, _mobopttypes), 2397c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField('olen', 16), 2398c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ShortField('hni', 0), 2399c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ShortField('coni', 0) ] 2400c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = 2 ; y = 0 # alignment requirement: 2n 2401c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 240277132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass MIP6OptBindingAuthData(_MIP6OptAlign, Packet): 2403c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = 'MIPv6 Option - Binding Authorization Data' 2404c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField('otype', 5, _mobopttypes), 2405c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField('olen', 16), 2406c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil BitField('authenticator', 0, 96) ] 2407c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = 8 ; y = 2 # alignment requirement: 8n+2 2408c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2409c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptMobNetPrefix(_MIP6OptAlign, Packet): # NEMO - RFC 3963 2410c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = 'NEMO Option - Mobile Network Prefix' 2411c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("otype", 6, _mobopttypes), 24125bbe280843fec8d5955914c78f52cb9cef7d61a4Phil ByteField("olen", 18), 2413c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("reserved", 0), 2414c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("plen", 64), 2415c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IP6Field("prefix", "::") ] 2416c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = 8 ; y = 4 # alignment requirement: 8n+4 2417c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2418c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptLLAddr(_MIP6OptAlign, Packet): # Sect 6.4.4 of RFC 4068 2419c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "MIPv6 Option - Link-Layer Address (MH-LLA)" 2420c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("otype", 7, _mobopttypes), 2421c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("olen", 7), 2422c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteEnumField("ocode", 2, _rfc4068_lla_optcode), 2423c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("pad", 0), 2424c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil MACField("lla", ETHER_ANY) ] # Only support ethernet 2425c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = 0 ; y = 0 # alignment requirement: none 2426c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2427c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptMNID(_MIP6OptAlign, Packet): # RFC 4283 2428c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "MIPv6 Option - Mobile Node Identifier" 2429c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("otype", 8, _mobopttypes), 2430c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil FieldLenField("olen", None, length_of="id", fmt="B", 2431c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil adjust = lambda pkt,x: x+1), 2432c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteEnumField("subtype", 1, {1: "NAI"}), 2433c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil StrLenField("id", "", 2434c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil length_from = lambda pkt: pkt.olen-1) ] 2435c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = 0 ; y = 0 # alignment requirement: none 2436c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2437c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# We only support decoding and basic build. Automatic HMAC computation is 2438c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# too much work for our current needs. It is left to the user (I mean ... 2439c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# you). --arno 2440c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptMsgAuth(_MIP6OptAlign, Packet): # RFC 4285 (Sect. 5) 2441c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "MIPv6 Option - Mobility Message Authentication" 2442c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("otype", 9, _mobopttypes), 2443c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil FieldLenField("olen", None, length_of="authdata", fmt="B", 2444c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil adjust = lambda pkt,x: x+5), 2445c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteEnumField("subtype", 1, {1: "MN-HA authentication mobility option", 2446c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2: "MN-AAA authentication mobility option"}), 2447c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IntField("mspi", None), 2448c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil StrLenField("authdata", "A"*12, 2449c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil length_from = lambda pkt: pkt.olen-5) ] 2450c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = 4 ; y = 1 # alignment requirement: 4n+1 2451c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2452c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Extracted from RFC 1305 (NTP) : 2453c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# NTP timestamps are represented as a 64-bit unsigned fixed-point number, 2454c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# in seconds relative to 0h on 1 January 1900. The integer part is in the 2455c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# first 32 bits and the fraction part in the last 32 bits. 2456c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NTPTimestampField(LongField): 2457c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil epoch = (1900, 1, 1, 0, 0, 0, 5, 1, 0) 2458c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def i2repr(self, pkt, x): 2459c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if x < ((50*31536000)<<32): 2460c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return "Some date a few decades ago (%d)" % x 2461c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2462c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # delta from epoch (= (1900, 1, 1, 0, 0, 0, 5, 1, 0)) to 2463c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # January 1st 1970 : 2464c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil delta = -2209075761 2465c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil i = int(x >> 32) 2466c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil j = float(x & 0xffffffff) * 2.0**-32 2467c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil res = i + j + delta 2468c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil from time import strftime 2469c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil t = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime(res)) 2470c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2471c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return "%s (%d)" % (t, x) 2472c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2473c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptReplayProtection(_MIP6OptAlign, Packet): # RFC 4285 (Sect. 6) 2474c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "MIPv6 option - Replay Protection" 2475c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("otype", 10, _mobopttypes), 2476c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("olen", 8), 2477c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil NTPTimestampField("timestamp", 0) ] 2478c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = 8 ; y = 2 # alignment requirement: 8n+2 2479c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2480c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptCGAParamsReq(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.6) 2481c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "MIPv6 option - CGA Parameters Request" 2482c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("otype", 11, _mobopttypes), 2483c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("olen", 0) ] 2484c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = 0 ; y = 0 # alignment requirement: none 2485c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2486c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# XXX TODO: deal with CGA param fragmentation and build of defragmented 2487c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# XXX version. Passing of a big CGAParam structure should be 2488c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# XXX simplified. Make it hold packets, by the way --arno 2489c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptCGAParams(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.1) 2490c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "MIPv6 option - CGA Parameters" 2491c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("otype", 12, _mobopttypes), 2492c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil FieldLenField("olen", None, length_of="cgaparams", fmt="B"), 2493c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil StrLenField("cgaparams", "", 2494c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil length_from = lambda pkt: pkt.olen) ] 2495c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = 0 ; y = 0 # alignment requirement: none 2496c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2497c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptSignature(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.2) 2498c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "MIPv6 option - Signature" 2499c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("otype", 13, _mobopttypes), 2500c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil FieldLenField("olen", None, length_of="sig", fmt="B"), 2501c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil StrLenField("sig", "", 2502c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil length_from = lambda pkt: pkt.olen) ] 2503c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = 0 ; y = 0 # alignment requirement: none 2504c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2505c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptHomeKeygenToken(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.3) 2506c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "MIPv6 option - Home Keygen Token" 2507c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("otype", 14, _mobopttypes), 2508c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil FieldLenField("olen", None, length_of="hkt", fmt="B"), 2509c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil StrLenField("hkt", "", 2510c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil length_from = lambda pkt: pkt.olen) ] 2511c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = 0 ; y = 0 # alignment requirement: none 2512c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2513c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptCareOfTestInit(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.4) 2514c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "MIPv6 option - Care-of Test Init" 2515c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("otype", 15, _mobopttypes), 2516c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("olen", 0) ] 2517c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = 0 ; y = 0 # alignment requirement: none 2518c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2519c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptCareOfTest(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.5) 2520c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "MIPv6 option - Care-of Test" 2521c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("otype", 16, _mobopttypes), 2522c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil FieldLenField("olen", None, length_of="cokt", fmt="B"), 2523c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil StrLenField("cokt", '\x00'*8, 2524c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil length_from = lambda pkt: pkt.olen) ] 2525c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = 0 ; y = 0 # alignment requirement: none 2526c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2527c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptUnknown(_MIP6OptAlign, Packet): 2528c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = 'Scapy6 - Unknown Mobility Option' 2529c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("otype", 6, _mobopttypes), 2530c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil FieldLenField("olen", None, length_of="odata", fmt="B"), 2531c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil StrLenField("odata", "", 2532c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil length_from = lambda pkt: pkt.olen) ] 2533c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = 0 ; y = 0 # alignment requirement: none 2534c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2535c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilmoboptcls = { 0: Pad1, 2536c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1: PadN, 2537c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2: MIP6OptBRAdvice, 2538c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 3: MIP6OptAltCoA, 2539c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 4: MIP6OptNonceIndices, 2540c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 5: MIP6OptBindingAuthData, 2541c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 6: MIP6OptMobNetPrefix, 2542c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 7: MIP6OptLLAddr, 2543c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 8: MIP6OptMNID, 2544c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 9: MIP6OptMsgAuth, 2545c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 10: MIP6OptReplayProtection, 2546c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 11: MIP6OptCGAParamsReq, 2547c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 12: MIP6OptCGAParams, 2548c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 13: MIP6OptSignature, 2549c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 14: MIP6OptHomeKeygenToken, 2550c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 15: MIP6OptCareOfTestInit, 2551c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 16: MIP6OptCareOfTest } 2552c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2553c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2554c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Main Mobile IPv6 Classes 2555c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2556c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilmhtypes = { 0: 'BRR', 2557c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1: 'HoTI', 2558c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2: 'CoTI', 2559c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 3: 'HoT', 2560c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 4: 'CoT', 2561c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 5: 'BU', 2562c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 6: 'BA', 2563c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 7: 'BE', 2564c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 8: 'Fast BU', 2565c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 9: 'Fast BA', 2566c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 10: 'Fast NA' } 2567c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2568c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# From http://www.iana.org/assignments/mobility-parameters 2569c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbastatus = { 0: 'Binding Update accepted', 2570c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1: 'Accepted but prefix discovery necessary', 2571c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 128: 'Reason unspecified', 2572c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 129: 'Administratively prohibited', 2573c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 130: 'Insufficient resources', 2574c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 131: 'Home registration not supported', 2575c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 132: 'Not home subnet', 2576c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 133: 'Not home agent for this mobile node', 2577c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 134: 'Duplicate Address Detection failed', 2578c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 135: 'Sequence number out of window', 2579c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 136: 'Expired home nonce index', 2580c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 137: 'Expired care-of nonce index', 2581c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 138: 'Expired nonces', 2582c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 139: 'Registration type change disallowed', 2583c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 140: 'Mobile Router Operation not permitted', 2584c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 141: 'Invalid Prefix', 2585c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 142: 'Not Authorized for Prefix', 2586c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 143: 'Forwarding Setup failed (prefixes missing)', 2587c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 144: 'MIPV6-ID-MISMATCH', 2588c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 145: 'MIPV6-MESG-ID-REQD', 2589c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 146: 'MIPV6-AUTH-FAIL', 2590c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 147: 'Permanent home keygen token unavailable', 2591c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 148: 'CGA and signature verification failed', 2592c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 149: 'Permanent home keygen token exists', 2593c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 150: 'Non-null home nonce index expected' } 2594c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2595c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2596c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _MobilityHeader(Packet): 2597c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = 'Dummy IPv6 Mobility Header' 2598c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil overload_fields = { IPv6: { "nh": 135 }} 2599c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2600c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def post_build(self, p, pay): 2601c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil p += pay 2602c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil l = self.len 2603c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if self.len is None: 2604c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil l = (len(p)-8)/8 2605c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil p = p[0] + struct.pack("B", l) + p[2:] 2606c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if self.cksum is None: 2607c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil cksum = in6_chksum(135, self.underlayer, p) 2608c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil else: 2609c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil cksum = self.cksum 2610c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil p = p[:4]+struct.pack("!H", cksum)+p[6:] 2611c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return p 2612c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2613c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2614c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_Generic(_MobilityHeader): # Mainly for decoding of unknown msg 2615c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "IPv6 Mobility Header - Generic Message" 2616c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("nh", 59, ipv6nh), 2617c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("len", None), 2618c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteEnumField("mhtype", None, mhtypes), 2619c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("res", None), 2620c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None), 2621c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil StrLenField("msg", "\x00"*2, 2622c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil length_from = lambda pkt: 8*pkt.len-6) ] 2623c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2624c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2625c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2626c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO: make a generic _OptionsField 2627c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _MobilityOptionsField(PacketListField): 2628c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def __init__(self, name, default, cls, curpos, count_from=None, length_from=None): 2629c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil self.curpos = curpos 2630c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil PacketListField.__init__(self, name, default, cls, count_from=count_from, length_from=length_from) 2631c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2632c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def getfield(self, pkt, s): 2633c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil l = self.length_from(pkt) 2634c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s[l:],self.m2i(pkt, s[:l]) 2635c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2636c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def i2len(self, pkt, i): 2637c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return len(self.i2m(pkt, i)) 2638c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2639c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def m2i(self, pkt, x): 2640c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil opt = [] 2641c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil while x: 2642c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil o = ord(x[0]) # Option type 2643c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil cls = self.cls 2644c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if moboptcls.has_key(o): 2645c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil cls = moboptcls[o] 2646c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil try: 2647c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil op = cls(x) 2648c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil except: 2649c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil op = self.cls(x) 2650c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil opt.append(op) 26517b3e970663abd72697e17b70aba9943ae0dad404Phil if isinstance(op.payload, conf.raw_layer): 2652c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = op.payload.load 2653c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil del(op.payload) 2654c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil else: 2655c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil x = "" 2656c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return opt 2657c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2658c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def i2m(self, pkt, x): 2659c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil autopad = None 2660c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil try: 2661c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil autopad = getattr(pkt, "autopad") # Hack : 'autopad' phantom field 2662c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil except: 2663c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil autopad = 1 2664c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2665c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if not autopad: 2666c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return "".join(map(str, x)) 2667c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2668c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil curpos = self.curpos 2669c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil s = "" 2670c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil for p in x: 2671c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil d = p.alignment_delta(curpos) 2672c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil curpos += d 2673c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if d == 1: 2674c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil s += str(Pad1()) 2675c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif d != 0: 2676c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil s += str(PadN(optdata='\x00'*(d-2))) 2677c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil pstr = str(p) 2678c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil curpos += len(pstr) 2679c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil s += pstr 2680c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2681c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # Let's make the class including our option field 2682c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # a multiple of 8 octets long 2683c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil d = curpos % 8 2684c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if d == 0: 2685c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s 2686c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil d = 8 - d 2687c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if d == 1: 2688c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil s += str(Pad1()) 2689c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif d != 0: 2690c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil s += str(PadN(optdata='\x00'*(d-2))) 2691c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2692c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s 2693c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2694c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def addfield(self, pkt, s, val): 2695c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return s+self.i2m(pkt, val) 2696c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2697c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_BRR(_MobilityHeader): 2698c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "IPv6 Mobility Header - Binding Refresh Request" 2699c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("nh", 59, ipv6nh), 2700c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("len", None), 2701c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteEnumField("mhtype", 0, mhtypes), 2702c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("res", None), 2703c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None), 2704c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ShortField("res2", None), 2705c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil _PhantomAutoPadField("autopad", 1), # autopad activated by default 2706c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil _MobilityOptionsField("options", [], MIP6OptUnknown, 8, 2707c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil length_from = lambda pkt: 8*pkt.len) ] 2708c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil overload_fields = { IPv6: { "nh": 135 } } 2709c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def hashret(self): 2710c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # Hack: BRR, BU and BA have the same hashret that returns the same 2711c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # value "\x00\x08\x09" (concatenation of mhtypes). This is 2712c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # because we need match BA with BU and BU with BRR. --arno 2713c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return "\x00\x08\x09" 2714c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2715c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_HoTI(_MobilityHeader): 2716c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "IPv6 Mobility Header - Home Test Init" 2717c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("nh", 59, ipv6nh), 2718c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("len", None), 2719c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteEnumField("mhtype", 1, mhtypes), 2720c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("res", None), 2721c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None), 2722f221c7f77a870b20b863a305c4411c2b572d002bGuillaume Valadon StrFixedLenField("reserved", "\x00"*2, 2), 2723c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil StrFixedLenField("cookie", "\x00"*8, 8), 2724c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil _PhantomAutoPadField("autopad", 1), # autopad activated by default 2725c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil _MobilityOptionsField("options", [], MIP6OptUnknown, 16, 2726c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil length_from = lambda pkt: 8*(pkt.len-1)) ] 2727c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil overload_fields = { IPv6: { "nh": 135 } } 2728c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def hashret(self): 2729c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.cookie 2730c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2731c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_CoTI(MIP6MH_HoTI): 2732c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "IPv6 Mobility Header - Care-of Test Init" 2733c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil mhtype = 2 2734c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def hashret(self): 2735c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.cookie 2736c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2737c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_HoT(_MobilityHeader): 2738c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "IPv6 Mobility Header - Home Test" 2739c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("nh", 59, ipv6nh), 2740c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("len", None), 2741c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteEnumField("mhtype", 3, mhtypes), 2742c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("res", None), 2743c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None), 2744c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ShortField("index", None), 2745c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil StrFixedLenField("cookie", "\x00"*8, 8), 2746c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil StrFixedLenField("token", "\x00"*8, 8), 2747c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil _PhantomAutoPadField("autopad", 1), # autopad activated by default 2748c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil _MobilityOptionsField("options", [], MIP6OptUnknown, 24, 2749c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil length_from = lambda pkt: 8*(pkt.len-2)) ] 2750c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil overload_fields = { IPv6: { "nh": 135 } } 2751c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def hashret(self): 2752c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.cookie 2753c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def answers(self): 2754c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if (isinstance(other, MIP6MH_HoTI) and 2755c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil self.cookie == other.cookie): 2756c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return 1 2757c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return 0 2758c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2759c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_CoT(MIP6MH_HoT): 2760c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "IPv6 Mobility Header - Care-of Test" 2761c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil mhtype = 4 2762c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def hashret(self): 2763c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.cookie 2764c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2765c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def answers(self): 2766c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if (isinstance(other, MIP6MH_CoTI) and 2767c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil self.cookie == other.cookie): 2768c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return 1 2769c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return 0 2770c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2771c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass LifetimeField(ShortField): 2772c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def i2repr(self, pkt, x): 2773c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return "%d sec" % (4*x) 2774c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2775c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_BU(_MobilityHeader): 2776c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "IPv6 Mobility Header - Binding Update" 2777c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("nh", 59, ipv6nh), 2778c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("len", None), # unit == 8 bytes (excluding the first 8 bytes) 2779c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteEnumField("mhtype", 5, mhtypes), 2780c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("res", None), 2781c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None), 2782c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("seq", None), # TODO: ShortNonceField 2783571ee9a1f1431f1ec7e654b5ee991e2118b994efPhil FlagsField("flags", "KHA", 7, "PRMKLHA"), 2784571ee9a1f1431f1ec7e654b5ee991e2118b994efPhil XBitField("reserved", 0, 9), 2785c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil LifetimeField("mhtime", 3), # unit == 4 seconds 2786c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil _PhantomAutoPadField("autopad", 1), # autopad activated by default 2787c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil _MobilityOptionsField("options", [], MIP6OptUnknown, 12, 2788c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil length_from = lambda pkt: 8*pkt.len - 4) ] 2789c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil overload_fields = { IPv6: { "nh": 135 } } 2790c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2791c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def hashret(self): # Hack: see comment in MIP6MH_BRR.hashret() 2792c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return "\x00\x08\x09" 2793c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2794c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def answers(self, other): 2795c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if isinstance(other, MIP6MH_BRR): 2796c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return 1 2797c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return 0 2798c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2799c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_BA(_MobilityHeader): 2800c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "IPv6 Mobility Header - Binding ACK" 2801c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("nh", 59, ipv6nh), 2802c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("len", None), # unit == 8 bytes (excluding the first 8 bytes) 2803c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteEnumField("mhtype", 6, mhtypes), 2804c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("res", None), 2805c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None), 2806c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteEnumField("status", 0, bastatus), 2807571ee9a1f1431f1ec7e654b5ee991e2118b994efPhil FlagsField("flags", "K", 3, "PRK"), 2808571ee9a1f1431f1ec7e654b5ee991e2118b994efPhil XBitField("res2", None, 5), 2809c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("seq", None), # TODO: ShortNonceField 2810c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("mhtime", 0), # unit == 4 seconds 2811c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil _PhantomAutoPadField("autopad", 1), # autopad activated by default 2812c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil _MobilityOptionsField("options", [], MIP6OptUnknown, 12, 2813c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil length_from = lambda pkt: 8*pkt.len-4) ] 2814c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil overload_fields = { IPv6: { "nh": 135 }} 2815c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2816c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def hashret(self): # Hack: see comment in MIP6MH_BRR.hashret() 2817c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return "\x00\x08\x09" 2818c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2819c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def answers(self, other): 2820c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if (isinstance(other, MIP6MH_BU) and 2821c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil other.mhtype == 5 and 2822c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil self.mhtype == 6 and 2823c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil other.flags & 0x1 and # Ack request flags is set 2824c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil self.seq == other.seq): 2825c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return 1 2826c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return 0 2827c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2828c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_bestatus = { 1: 'Unknown binding for Home Address destination option', 2829c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2: 'Unrecognized MH Type value' } 2830c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2831c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO: match Binding Error to its stimulus 2832c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_BE(_MobilityHeader): 2833c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil name = "IPv6 Mobility Header - Binding Error" 2834c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil fields_desc = [ ByteEnumField("nh", 59, ipv6nh), 2835c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("len", None), # unit == 8 bytes (excluding the first 8 bytes) 2836c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteEnumField("mhtype", 7, mhtypes), 2837c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("res", 0), 2838c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil XShortField("cksum", None), 2839c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteEnumField("status", 0, _bestatus), 2840c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ByteField("reserved", 0), 2841c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil IP6Field("ha", "::"), 2842c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil _MobilityOptionsField("options", [], MIP6OptUnknown, 24, 2843c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil length_from = lambda pkt: 8*(pkt.len-2)) ] 2844c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil overload_fields = { IPv6: { "nh": 135 }} 2845c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2846c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_mip6_mhtype2cls = { 0: MIP6MH_BRR, 2847c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 1: MIP6MH_HoTI, 2848c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2: MIP6MH_CoTI, 2849c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 3: MIP6MH_HoT, 2850c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 4: MIP6MH_CoT, 2851c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 5: MIP6MH_BU, 2852c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 6: MIP6MH_BA, 2853c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 7: MIP6MH_BE } 2854c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2855c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2856c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 2857c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 2858c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil### Traceroute6 ### 2859c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 2860c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 2861c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2862c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass AS_resolver6(AS_resolver_riswhois): 2863c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def _resolve_one(self, ip): 2864c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil """ 2865c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil overloaded version to provide a Whois resolution on the 2866c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil embedded IPv4 address if the address is 6to4 or Teredo. 2867c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil Otherwise, the native IPv6 address is passed. 2868c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil """ 2869c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2870c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if in6_isaddr6to4(ip): # for 6to4, use embedded @ 2871c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil tmp = inet_pton(socket.AF_INET6, ip) 2872c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil addr = inet_ntop(socket.AF_INET, tmp[2:6]) 2873c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif in6_isaddrTeredo(ip): # for Teredo, use mapped address 2874c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil addr = teredoAddrExtractInfo(ip)[2] 2875c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil else: 2876c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil addr = ip 2877c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2878c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil _, asn, desc = AS_resolver_riswhois._resolve_one(self, addr) 2879c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2880c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return ip,asn,desc 2881c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2882c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass TracerouteResult6(TracerouteResult): 2883c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def show(self): 2884c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.make_table(lambda (s,r): (s.sprintf("%-42s,IPv6.dst%:{TCP:tcp%TCP.dport%}{UDP:udp%UDP.dport%}{ICMPv6EchoRequest:IER}"), # TODO: ICMPv6 ! 2885c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil s.hlim, 2886c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil r.sprintf("%-42s,IPv6.src% {TCP:%TCP.flags%}"+ 288777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil "{ICMPv6DestUnreach:%ir,type%}{ICMPv6PacketTooBig:%ir,type%}"+ 288877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil "{ICMPv6TimeExceeded:%ir,type%}{ICMPv6ParamProblem:%ir,type%}"+ 288977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil "{ICMPv6EchoReply:%ir,type%}"))) 2890c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2891c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def get_trace(self): 2892c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil trace = {} 2893c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2894c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil for s,r in self.res: 2895c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if IPv6 not in s: 2896c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil continue 2897c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil d = s[IPv6].dst 2898c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if d not in trace: 2899c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil trace[d] = {} 2900c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2901c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil t = not (ICMPv6TimeExceeded in r or 2902c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ICMPv6DestUnreach in r or 2903c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ICMPv6PacketTooBig in r or 2904c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil ICMPv6ParamProblem in r) 2905c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2906c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil trace[d][s[IPv6].hlim] = r[IPv6].src, t 2907c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2908c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil for k in trace.values(): 2909c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil m = filter(lambda x: k[x][1], k.keys()) 2910c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if not m: 2911c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil continue 2912c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil m = min(m) 2913c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil for l in k.keys(): 2914c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if l > m: 2915c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil del(k[l]) 2916c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2917c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return trace 2918c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2919c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def graph(self, ASres=AS_resolver6(), **kargs): 2920c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil TracerouteResult.graph(self, ASres=ASres, **kargs) 2921c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2922c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef traceroute6(target, dport=80, minttl=1, maxttl=30, sport=RandShort(), 2923c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil l4 = None, timeout=2, verbose=None, **kargs): 2924c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil """ 2925c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil Instant TCP traceroute using IPv6 : 2926c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil traceroute6(target, [maxttl=30], [dport=80], [sport=80]) -> None 2927c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil """ 2928c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if verbose is None: 2929c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil verbose = conf.verb 2930c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2931c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if l4 is None: 2932c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil a,b = sr(IPv6(dst=target, hlim=(minttl,maxttl))/TCP(seq=RandInt(),sport=sport, dport=dport), 2933c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil timeout=timeout, filter="icmp6 or tcp", verbose=verbose, **kargs) 2934c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil else: 2935c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil a,b = sr(IPv6(dst=target, hlim=(minttl,maxttl))/l4, 2936c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil timeout=timeout, verbose=verbose, **kargs) 2937c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2938c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil a = TracerouteResult6(a.res) 2939c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2940c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if verbose: 2941c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil a.display() 2942c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2943c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return a,b 2944c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2945c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 2946c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 2947c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil### Sockets ### 2948c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 2949c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 2950c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2951c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass L3RawSocket6(L3RawSocket): 2952c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def __init__(self, type = ETH_P_IPV6, filter=None, iface=None, promisc=None, nofilter=0): 2953c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil L3RawSocket.__init__(self, type, filter, iface, promisc) 295477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil # NOTE: if fragmentation is needed, it will be done by the kernel (RFC 2292) 2955c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil self.outs = socket.socket(socket.AF_INET6, socket.SOCK_RAW, socket.IPPROTO_RAW) 2956c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type)) 2957c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2958c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef IPv6inIP(dst='203.178.135.36', src=None): 2959c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil _IPv6inIP.dst = dst 2960c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil _IPv6inIP.src = src 2961c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if not conf.L3socket == _IPv6inIP: 2962c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil _IPv6inIP.cls = conf.L3socket 2963c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil else: 2964c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil del(conf.L3socket) 2965c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return _IPv6inIP 2966c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2967c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _IPv6inIP(SuperSocket): 2968c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil dst = '127.0.0.1' 2969c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil src = None 2970c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil cls = None 2971c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2972c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def __init__(self, family=socket.AF_INET6, type=socket.SOCK_STREAM, proto=0, **args): 2973c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil SuperSocket.__init__(self, family, type, proto) 2974c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil self.worker = self.cls(**args) 2975c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2976c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def set(self, dst, src=None): 2977c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil _IPv6inIP.src = src 2978c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil _IPv6inIP.dst = dst 2979c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2980c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def nonblock_recv(self): 2981c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil p = self.worker.nonblock_recv() 2982c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self._recv(p) 2983c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2984c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def recv(self, x): 2985c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil p = self.worker.recv(x) 2986c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self._recv(p, x) 2987c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2988c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def _recv(self, p, x=MTU): 2989c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if p is None: 2990c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return p 2991c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil elif isinstance(p, IP): 2992c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil # TODO: verify checksum 2993c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if p.src == self.dst and p.proto == socket.IPPROTO_IPV6: 2994c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil if isinstance(p.payload, IPv6): 2995c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return p.payload 2996c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return p 2997c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 2998c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil def send(self, x): 2999c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil return self.worker.send(IP(dst=self.dst, src=self.src, proto=socket.IPPROTO_IPV6)/x) 3000c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 3001c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 3002c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 3003c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 3004c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil### Layers binding ### 3005c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 3006c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################################################################# 3007c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 3008614f54fc4b269030ba2934b6c353fb43de886e04Philconf.l3types.register(ETH_P_IPV6, IPv6) 3009614f54fc4b269030ba2934b6c353fb43de886e04Philconf.l2types.register(31, IPv6) 3010c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil 3011c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(Ether, IPv6, type = 0x86dd ) 3012e0602343e528b8c9a53f20a0a40994eb1bb33436rbu@localhost.localdomainbind_layers(CookedLinux, IPv6, proto = 0x86dd ) 3013c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPerror6, TCPerror, nh = socket.IPPROTO_TCP ) 3014c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPerror6, UDPerror, nh = socket.IPPROTO_UDP ) 3015c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPv6, TCP, nh = socket.IPPROTO_TCP ) 3016c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPv6, UDP, nh = socket.IPPROTO_UDP ) 3017c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IP, IPv6, proto = socket.IPPROTO_IPV6 ) 3018c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPv6, IPv6, nh = socket.IPPROTO_IPV6 ) 301917b4ef20fe8a6ca5e1387900ca329c5d1bcfe05dGuillaume Valadonbind_layers(IPv6, IP, nh = socket.IPPROTO_IPIP ) 3020