blob: d70cd3fcb0698f00255610e0691fa2d4a0b1a112 [file] [log] [blame]
Zesstra@Morgengrauen5cad50a2016-04-19 21:44:10 +02001intermud v2.5
2*************
3
4Abstract
5========
6This documents describes how intermud data is send across the internet in the
7protocol specification v2.5.
8This specification is derived from Zebedee Intermud (aka Intermud 2) and
9intends to be compatible to it, i.e. hosts conforming to both protocols should
10be able to exchange data. The aim of v2.5 is to deprecate several historic
11ambiguities, define a more consistent (stricter, less implementation-defined)
12behaviour, add some optional system services and improve reliability and
13remove spoofability of MUDs by introducing hash based message authentication
14codes.
15
16Introduction
17============
18
19Overview
20--------
21The intermud protocols define, how (players on) different muds can
22communicate with each other. There are several different variants.
23In version 2 all muds are peers and directly talking to each other. There
24is no central router. Version 2.5 keeps this behaviour but intends to
25strengthen the P2P character of the intermud by defining a default
26behaviour of learning other peers from one known peer.
27The participants of the intermud are intended to be MUDs, not
28individual players.
29
30Terminology
31-----------
32The capitalized key words "MUST", "MUST NOT", "REQUIRED", "SHALL",
33"SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and
34"OPTIONAL" in this document are to be interpreted as described in BCP
3514, RFC 2119 [TERMS].
36
37MUD
38 multi user dungeon
39intermud peer
40 a participant in the intermud
41inetd
42 a program encoding and sending and receiving and decoding intermud data
43peer address
44 IP address of a peer (MUD)
Zesstra@Morgengrauenf14175b2016-05-27 22:49:29 +020045MUD name / peer name / peer identifier
46 a name (string) for a peer (MUD). If a peer has a key, the name is just a
47 symbolic name for a peer with this key. Otherwise, the peer name is the
48 unique identifier.
49 An inetd implementation MAY accept more than one peer with the same name as
50 long as their keys are different. However, it SHOULD keep a consistent
51 mapping between key and peer name.
Zesstra@Morgengrauen5cad50a2016-04-19 21:44:10 +020052
Zesstra79cdbe52016-04-22 19:26:49 +020053Host list / Peer data
54=====================
55A peer **MUST** store the following data about other known peers:
56
57* peer name (unique) (name)
58* public key (unique), if available (pkey)
59* peer address (ip)
60* receiving peer port (port)
Zesstraca0502f2016-04-24 20:11:54 +020061* time of last contact (last_contact)
62* time of first contact (first_contact)
Zesstra79cdbe52016-04-22 19:26:49 +020063* reputation (trust) of that peer (reputation)
64
65A peer **SHOULD** store the following data about other known peers:
66
67* list of supported services (services)
Zesstraca0502f2016-04-24 20:11:54 +020068* last seen intermud version (im_version)
Zesstra79cdbe52016-04-22 19:26:49 +020069* expiration time (ncttl)
70* MTU of the peer (mtu)
71
72A peers public key would be the best unique identifier. However, in the
73intermud a peer needs a unique symbolic name to address it. So a peers name
74and its public key should both be used as unique and long-lived identifier.
75
76But a peer MAY change its name by either announcing it or by just using a new
77name. If the public key remains the same, the entry in the peer list should
78be updated accordingly.
79
80If a peer claims to have a name that already exists, but its public key does
81not match the known public key of the existing peer entry, the new peer **MUST
82NOT** be entered in the peer list. Instead, any packets from that peer
83**SHOULD** be discarded. An implementation MAY notify the operator about this.
84
85When a peer starts up, it **SHOULD** make itself known by pinging known peers
86or sending a HELO packet.
87
88Host keys
89---------
90Each host **MUST** have an elliptic curve private/public key pair for ECDSA or
91EdDSA signatures using one of the following curves:
92
93* secp256r1 / prime256v1
94* Curve25519
95* secp521r1
96
97This *identity key* is long-lived. Bascically, the intermud peer name and its
98reputation tie to this identity key.
99
Zesstra@Morgengrauenf14175b2016-05-27 22:49:29 +0200100When receiving an IM 2.5+ packet from a peer with unknown public key, the
101receiver requests the sender's public key with a HELO packet (see below) and
102stores it (trust on first use).
103
104
105Peer name
106---------
107If a peer has a key, the name is just a symbolic name for a peer with this
108key. Otherwise, the peer name is the unique identifier.
109
110An inetd implementation MAY accept more than one peer with the same name as
111long as their keys are different. However, it SHOULD keep a consistent mapping
112between key and peer name.
113
114
Zesstra79cdbe52016-04-22 19:26:49 +0200115Reputation
116----------
117The reputation is a score that symbolizes how trustworthy a peer is. It may be
118used for a number of decisions. By default, the reputation score is used for
119the following:
120
121* scaling factor when exchanging peer information (see below)
122* peer expiration time since last contact (ncttl)
123* services that are offered to the other peer
124
125Specififally, to prevent spam and misuse, services like public channel
126messages and intermud mail **SHOULD** be restricted to peers with a reputation
127> 0. A peer may also restrict the accessibility of user depending on the
128reputation of the sending peer (e.g. beginners can't be disturbed from freshly
129known intermud peers).
130
131By default, a new peer starts with a score of 0 (which basically means, the
132information it offers, is not trusted). After a peer has been known for some
133time, its score gets increased:
134
135========== ==============
136time known score increase
137========== ==============
1387 days +1
1393 months +1
1401 year +1
141========== ==============
142
143A reputation of more than 3 can only be assigned by an operator.
144
145A negative reputation is possible (e.g. manually assigned by operators) and
146should be used to restrict services. Peers with negativ reputation should also
147be kept longer in the peer list.
148
149Peer expiration
150---------------
151A peer should expire peers from its host list some time after the last contact. The
152expiration time may be chosen by the operator.
153
154However, to prevent rogue peers impersonating other peers, peers **MUST NOT**
155be expired before 48h or a time this peer announced earlier (see module...
156TODO) passed without contact.
157
158========== ===============
159reputation expiration time
160========== ===============
1610 72h
1621 14 days
1632 3 months
1643 6 months
1654+ 12 months
166========== ===============
167
168If a peer announces it wants to be remembered for longer than 72h without
169contact, this wish MAY be respected and the decision MAY be based on its
170reputation. A peer **SHOULD NOT** request more then 12 months.
171
172An implementation **MAY** may move offline peers to a separate list for
173bookkeeping after some time and stop trying to contact it anymore. This keeps
174the active peer list short and efficient. However the 'long offline' peers
175should still be remembered to keep the binding of public key and name.
176
177If a peer has problems keeping track of peers, it **SHOULD** prefer to
178temporarily stop accepting new peers instead of expiring known ones.
179If a peer experiences too much intermud traffic (or other resource drains), it
180**MAY** favor peers with higher reputation.
181
182Automatic update of peer data
183-----------------------------
184When receiving a v2.5 packet with valid HMAC from an address and/or port that
185differs from the one in the peer list, the peer entry **SHOULD** be updated to
186the new address/port.
187
188If the address or port of a peer changes, this peer **SHOULD** send a ping to
189known peers to announce the new address or port.
190
191When receiving a legacy mode packet, the peer entry **MAY** be updated.
192However, this carries the risk of rogue peers successfully impersonating
193another peer for an extended time.
194
195An inetd **SHOULD** contact the known peers at least once per 24h to check if
196it is still online and reachable (ping or helo).
197
198Update of the public key
199------------------------
200There ist a way to perform an update of the public key without operator
201intervention. The new public key **MUST** be received in a v2.5 packet with
202valid signature.
203
204A peer may inform other peers about an update of its public key by
205sending a push notification - TODO fill in module - Such an
206update **SHOULD** be honored.
207
Zesstra@Morgengrauen5cad50a2016-04-19 21:44:10 +0200208
209Transport layer
210===============
211Data between intermud peers is sent as UDP packets (datagrams) over
212IP.
213Each peer listens on one port and uses one to send data. This kind of
214transfer is inherently unreliable, but it's fast and doesn't use up
215file descriptors.
216
217Packet length (MTU)
218-------------------
219A peer **MUST** be able to send and receive datagrams of at least 1024
220byte length. The default packet length **SHOULD** be 1024 bytes. If a peer
221announces a greater possible length limit, that **SHOULD** be used by other peers
222when sending packets to this peer.
223
Zesstra@Morgengrauen20219212016-04-20 22:34:41 +0200224A peer may announce the largest reliable packet (maximum transmission unit,
225maximum size of datagram) it can receive when asked with the QUERY module
226which should be the preferred way.
227
228If the MTU cannot be determined with a QUERY, the two peers should try to
229determine them by sending heartbeat packets of increasing size to the other
230peer (see below).
231
232The packet size that is used for sending **SHOULD** be the smaller of the
233maximum packet length of the two communicating peers.
234
Zesstra@Morgengrauen5cad50a2016-04-19 21:44:10 +0200235Packet format
236-------------
237All information is encoded and transferred as a string of bytes. The header
238names **SHOULD** consist of ASCII characters.
239Each packet sent consists of a string as follows:
240
Zesstra@Morgengrauenf14175b2016-05-27 22:49:29 +0200241 S:xxx|NAME:xxx|V:nnn|F:nnn|header1:body1|headerN:bodyN|DATA:body-data
Zesstra@Morgengrauen5cad50a2016-04-19 21:44:10 +0200242
243In other words, a header name, followed by a : and then the data
244associated with this header. Each field, consisting of a header/body pair, is
245separated by the | character. This means that headers and their body cannot
246contain the | character. Peers **SHOULD** check for this in outgoing
247packets to avoid decoding errors at the receiving end.
248
249The exception to this is the DATA field. If it is present, it **MUST**
250be positioned at the end of the packet. Once a DATA header is
251found, everything following it is interpreted as the body of the DATA
252field. This means it can contain special characters without error and
253it is used to carry the main body or data of all packets.
254
Zesstra@Morgengrauenf14175b2016-05-27 22:49:29 +0200255The fields S (packet signature), NAME (the sending peers name), V (version)
256and F (flags) **MUST** be in this order at the start of the packet before any
257other fields. These 4 fields are also referred to as the 'packet header'. The
258general layout of packets is:
Zesstra@Morgengrauen09eef282016-04-21 23:00:38 +0200259
Zesstra@Morgengrauen18f4e042016-05-07 11:02:19 +0200260 [fragmentation header|]packet header|packet payload/data
Zesstra@Morgengrauen09eef282016-04-21 23:00:38 +0200261
262The packet header **MUST NOT** be larger than 512 bytes.
263
Zesstra@Morgengrauen5cad50a2016-04-19 21:44:10 +0200264By convention, predefined system fields will use capital letters for
265field headers and custom headers used by specific applications will
266use lowercase names to avoid clashes.
267
268A header name **MUST** be unique in a packet.
269
Zesstra@Morgengrauenf14175b2016-05-27 22:49:29 +0200270An implemention **MUST** support at least 32 fields per packet.
Zesstra@Morgengrauen5cad50a2016-04-19 21:44:10 +0200271
272Fragmented packets
273------------------
274If a packet exceeds the maximum packet length, it **MUST** be split
275(fragmented) into individual packets small enough.
276Each fragment **MUST** start with a fragmentation header describing how the
277fragments are to be reassembled at the receiving end.
278
279These fragmentation headers are of the format:
280
Zesstra@Morgengrauen09eef282016-04-21 23:00:38 +0200281 PKT:peername:packet-id:packet-number/total-packets|S:xxx|rest-of-packet
Zesstra@Morgengrauen5cad50a2016-04-19 21:44:10 +0200282
283In this case, the mudname and packet-id combine to form a unique id
Zesstra@Morgengrauenf14175b2016-05-27 22:49:29 +0200284for the packet. The packet id is the same number used for the header field ID
285(see below). The packet-number and total-packets information is
Zesstra@Morgengrauen5cad50a2016-04-19 21:44:10 +0200286used to determine when all buffered packets have been received. The
287rest-of-packet part is not parsed, but is stored while the receiver
288awaits the other parts of the packet. When/if all parts have been
Zesstraca0502f2016-04-24 20:11:54 +0200289received they are concatenated (without the fragmentation header and S fields
Zesstra@Morgengrauen20219212016-04-20 22:34:41 +0200290of the individual fragments) and decoded as a normal packet.
291
292When storing fragments of a packet, the receiver **MUST** use a unique packet
Zesstra@Morgengrauenf14175b2016-05-27 22:49:29 +0200293id which uses the peer name and the sent packet-id.
Zesstra@Morgengrauen20219212016-04-20 22:34:41 +0200294
295Any peer **MUST** support at least 100 fragments per packet.
Zesstra@Morgengrauen5cad50a2016-04-19 21:44:10 +0200296
Zesstra@Morgengrauen09eef282016-04-21 23:00:38 +0200297Each fragment **MUST** contain its own valid signature in the field S.
Zesstra@Morgengrauen5cad50a2016-04-19 21:44:10 +0200298
299The sender **SHOULD** send the fragments in the correct order. However, the
300receiver **MUST** assume the fragments arrive in any order.
301
302The sender **MUST** send all fragments of a packet within 30 s from sending the
303first fragment.
304The receiver **MUST** wait for fragments at least 60 s after the first fragment
305arrived. After this, the receiver may discard any fragments of this packet and
306therefore the packet as a whole.
307
308Packet encoding
309---------------
310Only 2 generic data types are supported (namely strings and integers). All
311other data types **MUST** be expressed as strings or integers.
312
313On encoding integers are simply converted to a corresponding string.
314Strings **MUST** be prefixed with the character $. If the first character of a
315string is the $ character, it is escaped by prepending another $ character.
316
Zesstra@Morgengrauen09eef282016-04-21 23:00:38 +0200317Packet signatures
318-----------------
Zesstra@Morgengrauen20219212016-04-20 22:34:41 +0200319For packet validation and to prevent tampering on the wire and spoofing of
Zesstra@Morgengrauen09eef282016-04-21 23:00:38 +0200320peers, each packet sent **MUST** contain a field S containing the EC-DSA
321signature of the packet.
Zesstra@Morgengrauen20219212016-04-20 22:34:41 +0200322
Zesstra@Morgengrauen09eef282016-04-21 23:00:38 +0200323The first byte of the MAC field specifies the method and curve used. In intermud
Zesstra@Morgengrauen20219212016-04-20 22:34:41 +0200324v2.5 the following algorithms **MUST** be supported:
325
Zesstraca0502f2016-04-24 20:11:54 +0200326* (a) Ed25519 + SHA512
Zesstra@Morgengrauen20219212016-04-20 22:34:41 +0200327
Zesstraca0502f2016-04-24 20:11:54 +0200328The recommended method is Ed25519 + SHA512
Zesstra@Morgengrauen20219212016-04-20 22:34:41 +0200329
Zesstra@Morgengrauen09eef282016-04-21 23:00:38 +0200330The transferred data is the complete packet string **without** the field S.
331After the packet (or fragment) is encoded (without the field S), the signature
332is calculated using the private EC key and then inserted into the packet
333string either at the beginning of the packet or (for fragments) at the end of
334the fragmentation header.
Zesstra@Morgengrauen20219212016-04-20 22:34:41 +0200335
336Packet validation
337-----------------
338Upon receiving a fragment or packet, the receiver **MUST** first try to
Zesstra@Morgengrauen09eef282016-04-21 23:00:38 +0200339validate the signature in the field S, if a public key for the sending peer is
340known. The receiver extracts the whole field from the received string and
341verifies the signature. If signature can't be verified, the receiver **MUST**
342discard the fragment or packet.
Zesstra@Morgengrauen20219212016-04-20 22:34:41 +0200343
344Fragments are then stored until the packet is completed or the timeout is
345exceeded.
346
347The receiver **SHOULD** parse and decode the packet only after this initial
348validation. If the packet is malformed and cannot be parsed, the receiver
349**MUST** discard the packet.
350
351The intermud protocol versions of peers **SHOULD** be stored and no packets in
352an older protocol version **SHOULD** be accepted.
353
Zesstra@Morgengrauen5cad50a2016-04-19 21:44:10 +0200354Packet decoding
355---------------
356On decoding, any string with a $ as its first character will have it removed
357and will then be treated as a string.
358Any other strings will be converted to integers.
359
Zesstra@Morgengrauen09eef282016-04-21 23:00:38 +0200360The fields S, V and F **SHOULD** be stripped from the packet data that is
Zesstra@Morgengrauen5cad50a2016-04-19 21:44:10 +0200361transferred from the inetd implementation to the application.
362
363Legacy mode packets and encoding
364--------------------------------
Zesstra@Morgengrauen20219212016-04-20 22:34:41 +0200365Any intermud v2.5 peer **MUST** send data as described above. However, unless
366in a so-called strict mode, a receiving peer **MUST** accept data in a relaxed
367format that is sent by older intermud peers. Unless in strict mode, the following
368deviations are acceptable when receiving:
Zesstra@Morgengrauen5cad50a2016-04-19 21:44:10 +0200369
Zesstra@Morgengrauen09eef282016-04-21 23:00:38 +0200370* The packet header (S, V and F fields) is missing.
Zesstra@Morgengrauen5cad50a2016-04-19 21:44:10 +0200371* A string **MAY** be prefixed with the character $, but does not have to, unless
372 there ambiguity as to wether they should be decoded as a string or an
373 integer. If a string is losslessly convertable to an integer and back to a
374 string, it **MUST** be prefixed by $.
375 This means however, that any string not starting with $ **MUST** be checked
376 whether it is to be interpreted as integer or string.
377
Zesstra@Morgengrauen20219212016-04-20 22:34:41 +0200378However, a packet **MUST NOT** be parsed as legacy mode packet, if one of the
379following conditions are met:
Zesstra@Morgengrauen5cad50a2016-04-19 21:44:10 +0200380
Zesstra@Morgengrauen09eef282016-04-21 23:00:38 +0200381* the packet contains the field S
Zesstra@Morgengrauen20219212016-04-20 22:34:41 +0200382* the packet contains a version field F with a version of at least 2500
383* the receiving peer operates in strict mode
384
385After a packet conforming to protocol version >= 2.5 (>=2500) was received
Zesstra@Morgengrauen09eef282016-04-21 23:00:38 +0200386from a peer (this implies the succesful validation of the signature), legacy mode
Zesstra@Morgengrauen20219212016-04-20 22:34:41 +0200387packets from that peer **MUST NOT** be accepted without manual intervention of
388an operator or expiration of the peer from the peer list.
389
390If a peer sends to a peer with a known protocol version older than v2.5 it
391**MAY** send the data as a legacy mode packet. However, this is not recommended.
392
393Strict mode
394-----------
395To prevent spoofing of other muds, an operator MAY decide to operate in strict
Zesstra@Morgengrauen09eef282016-04-21 23:00:38 +0200396mode. In this mode, the peer accepts intermud v2.5 packets with a valid S
397field only and discards all other packets.
398In other words, it disables the compatibility with peers older than v2.5 and
399does not communicate with unknown peers.
Zesstra@Morgengrauen20219212016-04-20 22:34:41 +0200400
401Request bookkeeping
402-------------------
403When sending a request that expects/requires an answer, the sender **MUST**
404keep track of the request to relate any answers to the original request.
405
406Any peer **MUST** be able to keep track of at least 100 requests.
407
408If the answer of a request does not arrive within 60s, the request **SHOULD**
409be expired (timeout).
410
411
Zesstra@Morgengrauen5cad50a2016-04-19 21:44:10 +0200412Defined system headers / fields
413===============================
414The fields defined in this section **MUST NOT** be used in any application sending
415data via intermud. The sending inetd **SHOULD** check for this during input
416validation before assembling a packet.
417
Zesstra@Morgengrauenf14175b2016-05-27 22:49:29 +0200418V
419 Intermud version used by the sender (integer)
420F
421 Packet flags (integer, binary complement of flags)
422S
423 Signature of the packet
424NAME
425 The name of the sending mud.
426HST
427 The IP address of the host from which a request was received.
428 This is set by the receiving mud and is not contained in
429 outgoing packets.
430UDP
431 The UDP port the local mud is receiving on.
432 This is set by the receiving mud and is not contained in
433 outgoing packets.
434ID
435 The packet id. This field is simply an integer which is set by
436 the sending inetd. The number is incremented each time a packet
437 is sent (zero is never used). The ID **MAY** wrap-around to 1 after some
438 time.
439 This field is only needed if a reply is expected. REPLY packets **MUST**
440 include the original request id. This is not done by the inetd. However,
441 implementations **SHOULD** check for a sane ID field in outgoing replies.
442PKT
443 The fragmentation header for packets which have been fragmented (see
444 above).
Zesstra@Morgengrauen20219212016-04-20 22:34:41 +0200445REQ
Zesstra@Morgengrauenf14175b2016-05-27 22:49:29 +0200446 The name of the intermud request that is being made of the
Zesstra@Morgengrauen5cad50a2016-04-19 21:44:10 +0200447 receiving mud. Standard requests that should be supported by
448 all systems are "ping" (PING), "query" (QUERY), and "reply"
449 (REPLY). The PING request is used to determine wether or not a
450 mud is active. The QUERY request is used to query a remote mud
451 for information about itself (look at the udp/query module for
452 details of what information can be requested). The REPLY request
453 is special in that it is the request name used for all replies
454 made to by mud B to an initial request made by a mud A. It is
455 mud A's responsibility to keep track of the original request
Zesstra@Morgengrauenf14175b2016-05-27 22:49:29 +0200456 type so that the reply can be handled appropriately.
Zesstra@Morgengrauen20219212016-04-20 22:34:41 +0200457SND
Zesstra@Morgengrauenf14175b2016-05-27 22:49:29 +0200458 The name of the person or object which sent the request or to
Zesstra@Morgengrauen5cad50a2016-04-19 21:44:10 +0200459 whom replies should be directed. This is essential if a reply
Zesstra@Morgengrauen20219212016-04-20 22:34:41 +0200460 is expected.
Zesstra@Morgengrauenf14175b2016-05-27 22:49:29 +0200461RCPNT
462 The body of this field should contain the recipient the message
463 is to be sent to if applicable.
Zesstra@Morgengrauen20219212016-04-20 22:34:41 +0200464DATA
Zesstra@Morgengrauen5cad50a2016-04-19 21:44:10 +0200465 This field should contain the main body of any packet. It is
466 the only field that can contain special delimiting characters
467 without error.
Zesstra@Morgengrauen20219212016-04-20 22:34:41 +0200468SYS
469 (SYSTEM) Contains special system flags. The only system flag used at
Zesstra@Morgengrauen5cad50a2016-04-19 21:44:10 +0200470 present is TIME_OUT. This is included in packets returned due
471 to an expected reply timing out to differentiate it from an
472 actual reply.
473
474
475Intermud requests / modules
476===========================
477
478Mandatory requests / modules
479----------------------------
480The following are standard request types that **MUST** be supported
481by all systems:
482
Zesstra@Morgengrauen20219212016-04-20 22:34:41 +0200483ping
484^^^^
485This module should return a REPLY packet that contains the
486original requests ID in it's ID field and the SENDER in it's
487RECIPIENT field. It should also include an appropriate string
488in the DATA field, eg. "Mud-Name is alive.\n"
489
Zesstra@Morgengrauenf14175b2016-05-27 22:49:29 +0200490Request::
491
492 "...|REQUEST:ping|ID:42|DATA:Morgengrauen is alive.\n"
493
494Answer::
495
496 "...|REQUEST:reply|ID:42|DATA:Unitopa is alive.\n"
497
498
Zesstra@Morgengrauen09eef282016-04-21 23:00:38 +0200499helo
500^^^^
Zesstra@Morgengrauenf14175b2016-05-27 22:49:29 +0200501Used to exchange information like the public key. The sender sends its name
502and public key, the receiver answers with its own name and public key, encoded
503as JSON.
504
505Having to send one's own public key makes UDP amplification attacks (e.g.
506sending a small packet with a faked source which causes a larger packet be
507sent to the victim) more difficult, since there is no amplification.
508
509Optionally, more data **MAY** be included: desired mtu in bytes (mtu), ...
510
511Request::
512
513 "...|REQUEST:helo|ID:42|DATA:{ \"pkey\": \"xxx\", \"name\": \"Morgengrauen\" }"
514
515Answer::
516
517 "...|REQUEST:reply|ID:42|DATA:{ \"pkey\": \"yyy\", \"name\": \"Unitopia\" }"
518
Zesstra@Morgengrauen09eef282016-04-21 23:00:38 +0200519
Zesstra@Morgengrauen20219212016-04-20 22:34:41 +0200520query
521^^^^^
522This module expects the type of query requested to appear in the
523recieved DATA field. It should return a REPLY packet containing
524the original ID in the ID field, the SENDER in it's RECIPIENT
525field, and the query type in a QUERY field. The DATA field should
526contain the information requested.
Zesstra@Morgengrauen09eef282016-04-21 23:00:38 +0200527TODO: include asking for peer list in JSON format.
Zesstra@Morgengrauen5cad50a2016-04-19 21:44:10 +0200528
529
530Optional requests / modules
531----------------------------
Zesstra@Morgengrauen20219212016-04-20 22:34:41 +0200532These modules are completely optional and their availability at the discretion
533of the operator of a peer.
534