Vydané zdroje
Stáhnout zdroje ZIP
CH-J SM Mobile
Procházejte adresáře a soubory konkrétního vydání aplikace.
CH-J / SM Mobile
175 souborů
sm-mobile-20261016T185235Z-8e93ecc1b59a
Přidáno: · Sestaveno:
1
import 'dart:typed_data';3
/// ICMP (RFC 792) and ICMPv6 (RFC 4443) message types used by ping and4
/// traceroute.5
abstract final class IcmpType {6
static const echoReply4 = 0, unreachable4 = 3, echoRequest4 = 8;7
static const timeExceeded4 = 11;8
static const unreachable6 = 1, timeExceeded6 = 3;9
static const echoRequest6 = 128, echoReply6 = 129;10
}12
/// What a received ICMP message means for an outstanding echo request.13
enum IcmpKind { echoReply, timeExceeded, unreachable, other }15
/// A parsed ICMP message. For error messages, [id] and [seq] come from the16
/// echo request quoted inside the error, so the error can be matched to the17
/// probe that caused it.18
class IcmpMessage {19
final IcmpKind kind;20
final int type, code;21
final int? id, seq;23
/// For errors about a UDP or TCP packet: the quoted transport protocol24
/// (17 or 6) and its source and destination ports.25
final int? protocol, sourcePort, destinationPort;26
const IcmpMessage(27
this.kind,28
this.type,29
this.code, {30
this.id,31
this.seq,32
this.protocol,33
this.sourcePort,34
this.destinationPort,35
});37
/// ICMP "port unreachable": the destination itself answered a UDP probe.38
bool portUnreachable(bool v6) =>39
kind == IcmpKind.unreachable && code == (v6 ? 4 : 3);40
@override41
String toString() =>42
'IcmpMessage($kind, type $type code $code '43
'id $id seq $seq)';44
}46
/// Internet checksum (RFC 1071).47
int icmpChecksum(Uint8List data) {48
var sum = 0;49
for (var i = 0; i + 1 < data.length; i += 2) {50
sum += (data[i] << 8) | data[i + 1];51
}52
if (data.length.isOdd) sum += data.last << 8;53
while (sum >> 16 != 0) {54
sum = (sum & 0xffff) + (sum >> 16);55
}56
return ~sum & 0xffff;57
}59
/// An echo request with [size] payload bytes. The IPv4 checksum is filled60
/// in; for ICMPv6 the kernel computes it over the pseudo-header.61
Uint8List buildEchoRequest({62
required bool v6,63
required int id,64
required int seq,65
int size = 56,66
}) {67
final packet = Uint8List(8 + size);68
packet[0] = v6 ? IcmpType.echoRequest6 : IcmpType.echoRequest4;69
packet[4] = (id >> 8) & 0xff;70
packet[5] = id & 0xff;71
packet[6] = (seq >> 8) & 0xff;72
packet[7] = seq & 0xff;73
for (var i = 0; i < size; i++) {74
packet[8 + i] = (0x20 + i) & 0xff;75
}76
if (!v6) {77
final sum = icmpChecksum(packet);78
packet[2] = sum >> 8;79
packet[3] = sum & 0xff;80
}81
return packet;82
}84
int _u16(Uint8List b, int at) => (b[at] << 8) | b[at + 1];86
/// Parses a received message. Darwin's ICMPv4 datagram sockets deliver the87
/// IPv4 header first ([ipHeader] true); Linux ping sockets and all ICMPv688
/// sockets deliver the ICMP message alone. Returns null for data too short89
/// or malformed to be an ICMP message.90
IcmpMessage? parseIcmp(91
Uint8List data, {92
required bool v6,93
bool ipHeader = false,94
}) {95
var at = 0;96
if (!v6 && ipHeader) {97
if (data.isEmpty || data[0] >> 4 != 4) return null;98
at = (data[0] & 0x0f) * 4;99
if (at < 20) return null;100
}101
if (data.length < at + 8) return null;102
final type = data[at], code = data[at + 1];103
final reply = v6 ? IcmpType.echoReply6 : IcmpType.echoReply4;104
if (type == reply) {105
return IcmpMessage(106
IcmpKind.echoReply,107
type,108
code,109
id: _u16(data, at + 4),110
seq: _u16(data, at + 6),111
);112
}113
final exceeded = v6 ? IcmpType.timeExceeded6 : IcmpType.timeExceeded4;114
final unreachable = v6 ? IcmpType.unreachable6 : IcmpType.unreachable4;115
final kind = type == exceeded116
? IcmpKind.timeExceeded117
: type == unreachable118
? IcmpKind.unreachable119
: IcmpKind.other;120
if (kind == IcmpKind.other) return IcmpMessage(kind, type, code);121
// The error quotes the offending packet: its IP header, then at least the122
// first 8 bytes of our echo request (type, code, checksum, id, sequence).123
final quoted = at + 8;124
int inner, protocol;125
if (v6) {126
// Fixed IPv6 header; extension headers are not followed.127
if (data.length < quoted + 40 + 8) return IcmpMessage(kind, type, code);128
protocol = data[quoted + 6];129
inner = quoted + 40;130
} else {131
if (data.length < quoted + 20 || data[quoted] >> 4 != 4) {132
return IcmpMessage(kind, type, code);133
}134
final length = (data[quoted] & 0x0f) * 4;135
if (length < 20 || data.length < quoted + length + 8) {136
return IcmpMessage(kind, type, code);137
}138
protocol = data[quoted + 9];139
inner = quoted + length;140
}141
if (protocol == 17 || protocol == 6) {142
// UDP and TCP both start with source and destination port.143
return IcmpMessage(144
kind,145
type,146
code,147
protocol: protocol,148
sourcePort: _u16(data, inner),149
destinationPort: _u16(data, inner + 2),150
);151
}152
if (protocol != (v6 ? 58 : 1)) return IcmpMessage(kind, type, code);153
final request = v6 ? IcmpType.echoRequest6 : IcmpType.echoRequest4;154
if (data[inner] != request) return IcmpMessage(kind, type, code);155
return IcmpMessage(156
kind,157
type,158
code,159
id: _u16(data, inner + 4),160
seq: _u16(data, inner + 6),161
);162
}164
/// The echo id and sequence of a packet this device sent, as returned with165
/// a Linux error-queue notification.166
({int id, int seq})? sentEcho(Uint8List data, {required bool v6}) {167
final request = v6 ? IcmpType.echoRequest6 : IcmpType.echoRequest4;168
if (data.length < 8 || data[0] != request) return null;169
return (id: _u16(data, 4), seq: _u16(data, 6));170
}SHA-256
89a8158d7865e10ebeefcd019b585129573fb247358cffd35e2503c8a2f9c9caCH-J Proprietary Software License 1.14 · Zdroje jsou zveřejněny pod CH-J Proprietary Software License 1.14. Jejich dostupnost nemění licenční podmínky ani neposkytuje další oprávnění.
SHA-256 archivu
46e427a43e87af091004f36145590bda8fe90086dfb0f631afeb5029fb0b5655