1# Copyright (C) 2018 antoine.torre <torreantoine1@gmail.com> 2## 3# This program is published under a GPLv2 license 4 5 6# scapy.contrib.description = ATA Over Internet 7# scapy.contrib.status = loads 8 9from scapy.packet import Packet, bind_layers 10from scapy.fields import FlagsField, XByteField, ByteField, XShortField, \ 11 ShortField, StrLenField, BitField, BitEnumField, ByteEnumField, \ 12 FieldLenField, PacketListField, FieldListField, MACField, PacketField, \ 13 ConditionalField, XIntField 14from scapy.layers.l2 import Ether 15from scapy.data import ETHER_ANY 16 17 18class IssueATACommand(Packet): 19 name = "Issue ATA Command" 20 fields_desc = [FlagsField("flags", 0, 8, "zezdzzaw"), 21 XByteField("err_feature", 0), 22 ByteField("sector_count", 1), 23 XByteField("cmd_status", 0xec), 24 XByteField("lba0", 0), 25 XByteField("lba1", 0), 26 XByteField("lba2", 0), 27 XByteField("lba3", 0), 28 XByteField("lba4", 0), 29 XByteField("lba5", 0), 30 XShortField("reserved", 0), 31 StrLenField("data", "", 32 length_from=lambda x: x.sector_count * 512)] 33 34 def extract_padding(self, s): 35 return "", s 36 37 38class QueryConfigInformation(Packet): 39 name = "Query Config Information" 40 fields_desc = [ShortField("buffer_count", 0), 41 ShortField("firmware", 0), 42 ByteField("sector_count", 0), 43 BitField("aoe", 0, 4), 44 BitEnumField("ccmd", 0, 4, {0: "Read config string", 45 1: "Test config string", 46 2: "Test config string prefix", 47 3: "Set config string", 48 4: "Force set config string"}), 49 FieldLenField("config_length", None, length_of="config"), 50 StrLenField("config", None, 51 length_from=lambda x: x.config_length)] 52 53 def extract_padding(self, s): 54 return "", s 55 56 57class Directive(Packet): 58 name = "Directive" 59 fields_desc = [ByteField("reserved", 0), 60 ByteEnumField("dcmd", 0, 61 {0: "No directive", 62 1: "Add mac address to mask list", 63 2: "Delete mac address from mask list"}), 64 MACField("mac_addr", ETHER_ANY)] 65 66 67class MacMaskList(Packet): 68 name = "Mac Mask List" 69 fields_desc = [ByteField("reserved", 0), 70 ByteEnumField("mcmd", 0, {0: "Read Mac Mask List", 71 1: "Edit Mac Mask List"}), 72 ByteEnumField("merror", 0, {0: "", 73 1: "Unspecified error", 74 2: "Bad dcmd directive", 75 3: "Mask List Full"}), 76 FieldLenField("dir_count", None, count_of="directives"), 77 PacketListField("directives", None, Directive, 78 count_from=lambda pkt: pkt.dir_count)] 79 80 def extract_padding(self, s): 81 return "", s 82 83 84class ReserveRelease(Packet): 85 name = "Reserve / Release" 86 fields_desc = [ByteEnumField("rcmd", 0, {0: "Read Reserve List", 87 1: "Set Reserve List", 88 2: "Force Set Reserve List"}), 89 FieldLenField("nb_mac", None, count_of="mac_addrs"), 90 FieldListField("mac_addrs", None, MACField("", ETHER_ANY), 91 count_from=lambda pkt: pkt.nb_mac)] 92 93 def extract_padding(self, s): 94 return "", s 95 96 97class AOE(Packet): 98 name = "ATA over Ethernet" 99 fields_desc = [BitField("version", 1, 4), 100 FlagsField("flags", 0, 4, ["Response", "Error", 101 "r1", "r2"]), 102 ByteEnumField("error", 0, {1: "Unrecognized command code", 103 2: "Bad argument parameter", 104 3: "Device unavailable", 105 4: "Config string present", 106 5: "Unsupported exception", 107 6: "Target is reserved"}), 108 XShortField("major", 0xFFFF), 109 XByteField("minor", 0xFF), 110 ByteEnumField("cmd", 1, {0: "Issue ATA Command", 111 1: "Query Config Information", 112 2: "Mac Mask List", 113 3: "Reserve / Release"}), 114 XIntField("tag", 0), 115 ConditionalField(PacketField("i_ata_cmd", IssueATACommand(), 116 IssueATACommand), 117 lambda x: x.cmd == 0), 118 ConditionalField(PacketField("q_conf_info", 119 QueryConfigInformation(), 120 QueryConfigInformation), 121 lambda x: x.cmd == 1), 122 ConditionalField(PacketField("mac_m_list", MacMaskList(), 123 MacMaskList), 124 lambda x: x.cmd == 2), 125 ConditionalField(PacketField("res_rel", ReserveRelease(), 126 ReserveRelease), 127 lambda x: x.cmd == 3)] 128 129 def extract_padding(self, s): 130 return "", s 131 132 133bind_layers(Ether, AOE, type=0x88A2) 134bind_layers(AOE, IssueATACommand, cmd=0) 135bind_layers(AOE, QueryConfigInformation, cmd=1) 136bind_layers(AOE, MacMaskList, cmd=2) 137bind_layers(AOE, ReserveRelease, cmd=3) 138