1# SPDX-License-Identifier: GPL-2.0-or-later 2# This file is part of Scapy 3# See https://scapy.net/ for more information 4# Copyright (C) 2009 Adline Stephane <adline.stephane@gmail.com> 5# Copyright 2018 Gabriel Potter <gabriel[]potter[]fr> 6 7""" 8Secure Neighbor Discovery (SEND) - RFC3971 9""" 10 11# scapy.contrib.description = Secure Neighbor Discovery (SEND) (ICMPv6) 12# scapy.contrib.status = loads 13 14 15from scapy.packet import Packet 16from scapy.fields import BitField, ByteField, FieldLenField, PacketField, \ 17 PacketLenField, ShortField, StrFixedLenField, StrLenField, UTCTimeField 18from scapy.layers.x509 import X509_SubjectPublicKeyInfo 19from scapy.layers.inet6 import icmp6ndoptscls, _ICMPv6NDGuessPayload 20from scapy.compat import chb 21from scapy.volatile import RandBin 22 23 24class ICMPv6NDOptNonce(_ICMPv6NDGuessPayload, Packet): 25 name = "ICMPv6NDOptNonce" 26 fields_desc = [ByteField("type", 14), 27 FieldLenField("len", None, length_of="nonce", fmt="B", adjust=lambda pkt, x: int(round((x + 2) / 8.))), # noqa: E501 28 StrLenField("nonce", "", length_from=lambda pkt: pkt.len * 8 - 2)] # noqa: E501 29 30 31class ICMPv6NDOptTmstp(_ICMPv6NDGuessPayload, Packet): 32 name = "ICMPv6NDOptTmstp" 33 fields_desc = [ByteField("type", 13), 34 ByteField("len", 2), 35 BitField("reserved", 0, 48), 36 UTCTimeField("timestamp", None)] 37 38 39class ICMPv6NDOptRsaSig(_ICMPv6NDGuessPayload, Packet): 40 name = "ICMPv6NDOptRsaSig" 41 fields_desc = [ByteField("type", 12), 42 FieldLenField("len", None, length_of="signature_pad", fmt="B", adjust=lambda pkt, x: (x + 20) // 8), # noqa: E501 43 ShortField("reserved", 0), 44 StrFixedLenField("key_hash", "", length=16), 45 StrLenField("signature_pad", "", length_from=lambda pkt: pkt.len * 8 - 20)] # noqa: E501 46 47 48class CGA_Params(Packet): 49 name = "CGA Parameters data structure" 50 fields_desc = [StrFixedLenField("modifier", RandBin(size=16), length=16), 51 StrFixedLenField("subprefix", "", length=8), 52 ByteField("cc", 0), 53 PacketField("pubkey", X509_SubjectPublicKeyInfo(), 54 X509_SubjectPublicKeyInfo)] 55 56 57class ICMPv6NDOptCGA(_ICMPv6NDGuessPayload, Packet): 58 name = "ICMPv6NDOptCGA" 59 fields_desc = [ByteField("type", 11), 60 FieldLenField("len", None, length_of="CGA_PARAMS", fmt="B", adjust=lambda pkt, x: (x + pkt.padlength + 4) // 8), # noqa: E501 61 FieldLenField("padlength", 0, length_of="padding", fmt="B"), 62 ByteField("reserved", 0), 63 PacketLenField("CGA_PARAMS", "", CGA_Params, length_from=lambda pkt: pkt.len * 8 - pkt.padlength - 4), # noqa: E501 64 StrLenField("padding", "", length_from=lambda pkt: pkt.padlength)] # noqa: E501 65 66 def post_build(self, p, pay): 67 l_ = len(self.CGA_PARAMS) 68 tmp_len = -(4 + l_) % 8 # Pad to 8 bytes 69 p = p[:1] + chb((4 + l_ + tmp_len) // 8) + chb(tmp_len) + p[3:4 + l_] 70 p += b"\x00" * tmp_len + pay 71 return p 72 73 74send_icmp6ndoptscls = {11: ICMPv6NDOptCGA, 75 12: ICMPv6NDOptRsaSig, 76 13: ICMPv6NDOptTmstp, 77 14: ICMPv6NDOptNonce 78 } 79icmp6ndoptscls.update(send_icmp6ndoptscls) 80