Geek++ · Dossier 19 / 25

Atlas des paquets, opcodes et encapsulation

Étude technique publique · 644 mots · ≈ 3 min de lecture attentive

Étude intégraleSans réflexion CODEXSources & constantes conservées
Wire protocol
E3
LEN
OP
PAYLOAD

famille · longueur · opcode · données

1. Pourquoi un atlas du wire protocol

eMule ne possède pas un unique espace d’opcodes. La signification d’un message dépend au minimum du transport, de la famille de protocole et du contexte dans lequel l’opcode est reçu.

Un identifiant utile d’un message est donc plutôt :

transport + famille de protocole + direction/contexte + opcode

Un même nombre d’opcode peut avoir une signification différente dans deux familles distinctes.

2. Octets de famille de protocole

Dans les sources eMule étudiées, les valeurs principales sont :

OP_EDONKEYHEADER      = 0xE3
OP_KADEMLIAHEADER     = 0xE4
OP_KADEMLIAPACKEDPROT = 0xE5
OP_PACKEDPROT         = 0xD4
OP_EMULEPROT          = 0xC5
OP_MLDONKEYPROT       = 0x00
OP_EDONKEYPROT        = OP_EDONKEYHEADER

Interprétation :

0xE3  espace historique eDonkey/eD2K
0xC5  extensions eMule
0xD4  paquet générique compressé
0xE4  Kad
0xE5  Kad compressé
0x00  marqueur MLDonkey dans le code étudié

3. Framing TCP

Le framing TCP eD2K/eMule étudié utilise un header de 6 octets :

+----------+----------------+--------+
| protocol | packet length  | opcode |
| 1 octet  | 4 octets       | 1 oct. |
+----------+----------------+--------+
|                payload             |
+------------------------------------+

Le champ packetlength inclut l’octet opcode et le payload. Autrement dit :

packetlength = 1 + payload_size
wire_size    = 5 + packetlength
             = 6 + payload_size

TCP étant un flux, ce champ de longueur est nécessaire pour reconstruire les frontières entre messages.

4. Framing UDP

UDP conserve la frontière du datagramme. Le framing est donc conceptuellement plus court :

protocol + opcode + payload

La taille du datagramme fournit déjà la limite extérieure du message.

5. Un opcode n’est pas une identité globale

Exemple important : la valeur 0x01 peut désigner des messages différents selon la famille et le canal.

Un analyseur correct ne doit donc jamais faire :

opcode == 0x01 => message X

sans avoir auparavant déterminé :

E3 ? C5 ? E4 ? E5 ?
TCP ? UDP ?
client ↔ serveur ?
client ↔ client ?

6. Compression de paquet et compression de données fichier

Deux concepts distincts coexistent.

OP_PACKEDPROT (0xD4) désigne un paquet générique dont le contenu protocolaire est compressé, typiquement avec zlib dans les échanges qui le supportent.

Cela ne doit pas être confondu avec OP_COMPRESSEDPART, qui concerne les données transférées d’un fichier.

Donc :

OP_PACKEDPROT
→ compression d'un paquet protocolaire

OP_COMPRESSEDPART
→ compression du contenu d'un bloc/segment de fichier

Les serveurs peuvent annoncer une capability de compression, notamment SRVCAP_ZLIB.

7. MultiPacket

Plusieurs générations de MultiPacket apparaissent dans le code :

OP_MULTIPACKET       = 0x92   // ancien / déprécié
OP_MULTIPACKET_EXT   = 0xA4   // ancien / déprécié
OP_MULTIPACKET_EXT2  = 0xA9
OP_MULTIPACKETANSWER_EXT2 = 0xB0

MULTIPACKET_EXT2 s’appuie sur FileIdentifier.

Un MultiPacket n’est pas simplement plusieurs trames TCP collées dans un seul send(). Il s’agit d’un payload protocolaire regroupant plusieurs sous-commandes logiques liées à un même contexte.

8. Les tags

Les tags constituent une couche de sérialisation placée dans le payload de nombreux messages.

Conceptuellement :

nom/id du tag
+ type
+ valeur

Le protocole historique a connu plusieurs formes :

noms de tags textuels
identifiants numériques courts
entiers 8/16/32/64 bits
chaînes
blobs
chaînes de taille fixe

Les tags expliquent une partie importante de l’extensibilité du protocole : un message peut transporter de nouvelles propriétés sans nécessairement redéfinir toute sa structure fixe.

9. Parsing défensif

L’atlas montre plusieurs surfaces classiques à valider avant d’utiliser les données :

longueur de paquet
nombre de tags
longueur des chaînes
longueur des blobs
type de tag
opcode valide dans la famille courante
payload minimal attendu
compression réellement décompressable

Le protocole ayant accumulé des variantes historiques, un parseur ne peut pas supposer qu’une donnée distante est cohérente uniquement parce qu’elle utilise un opcode connu.

10. Résumé du dossier 19

Le point central est que le wire protocol d’eMule est une superposition de namespaces et d’extensions. Pour comprendre un paquet, il faut lire sa famille, son transport, son opcode puis son payload. Les tags et les MultiPackets ajoutent ensuite des niveaux de sérialisation supplémentaires.


Dossier 19 terminé

Atlas des paquets, opcodes et encapsulation

← Dossier 18Dossier 20 →