Просмотр исходного кода

A few more revisions to new multicast verbs.

Adam Ierymenko 11 лет назад
Родитель
Сommit
ed0ba49502
6 измененных файлов с 116 добавлено и 52 удалено
  1. 12 0
      node/IncomingPacket.cpp
  2. 4 2
      node/Multicaster.cpp
  3. 13 1
      node/Multicaster.hpp
  4. 4 2
      node/OutboundMulticast.cpp
  5. 13 1
      node/OutboundMulticast.hpp
  6. 70 46
      node/Packet.hpp

+ 12 - 0
node/IncomingPacket.cpp

@@ -893,6 +893,18 @@ bool IncomingPacket::_doNETWORK_CONFIG_REFRESH(const RuntimeEnvironment *RR,cons
 	return true;
 }
 
+bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
+{
+}
+
+bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
+{
+}
+
+void IncomingPacket::_handleMulticastGatherResponse(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer,unsigned int startIdx)
+{
+}
+
 void IncomingPacket::_sendErrorNeedCertificate(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer,uint64_t nwid)
 {
 	Packet outp(source(),RR->identity.address(),Packet::VERB_ERROR);

+ 4 - 2
node/Multicaster.cpp

@@ -34,6 +34,7 @@
 #include "Switch.hpp"
 #include "Packet.hpp"
 #include "Peer.hpp"
+#include "CertificateOfMembership.hpp"
 #include "RuntimeEnvironment.hpp"
 
 namespace ZeroTier {
@@ -46,7 +47,7 @@ Multicaster::~Multicaster()
 {
 }
 
-void Multicaster::send(const RuntimeEnvironment *RR,uint64_t nwid,unsigned int limit,uint64_t now,const MulticastGroup &mg,const MAC &src,unsigned int etherType,const void *data,unsigned int len)
+void Multicaster::send(const RuntimeEnvironment *RR,uint64_t nwid,const CertificateOfMembership *com,unsigned int limit,uint64_t now,const MulticastGroup &mg,const MAC &src,unsigned int etherType,const void *data,unsigned int len)
 {
 	Mutex::Lock _l(_groups_m);
 	MulticastGroupStatus &gs = _groups[mg];
@@ -81,10 +82,11 @@ void Multicaster::send(const RuntimeEnvironment *RR,uint64_t nwid,unsigned int l
 			if (sn) {
 				Packet outp(sn->address(),RR->identity.address(),Packet::VERB_MULTICAST_GATHER);
 				outp.append(nwid);
-				outp.append((char)0); // TODO: include network membership cert
+				outp.append((uint8_t)((com) ? 0x01: 0x00));
 				mg.mac().appendTo(outp);
 				outp.append((uint32_t)mg.adi());
 				outp.append((uint32_t)((limit - (unsigned int)gs.members.size()) + 1)); // +1 just means we'll have an extra in the queue if available
+				if (com) com->serialize(outp);
 				outp.armor(sn->key(),true);
 				sn->send(RR,outp.data(),outp.size(),now);
 			}

+ 13 - 1
node/Multicaster.hpp

@@ -46,6 +46,7 @@
 namespace ZeroTier {
 
 class RuntimeEnvironment;
+class CertificateOfMembership;
 
 /**
  * Database of known multicast peers within a network
@@ -100,6 +101,7 @@ public:
 	 *
 	 * @param RR Runtime environment
 	 * @param nwid Network ID
+	 * @param com Certificate of membership to include or NULL for none
 	 * @param limit Multicast limit
 	 * @param now Current time
 	 * @param mg Multicast group
@@ -108,7 +110,17 @@ public:
 	 * @param data Packet data
 	 * @param len Length of packet data
 	 */
-	void send(const RuntimeEnvironment *RR,uint64_t nwid,unsigned int limit,uint64_t now,const MulticastGroup &mg,const MAC &src,unsigned int etherType,const void *data,unsigned int len);
+	void send(
+		const RuntimeEnvironment *RR,
+		uint64_t nwid,
+		const CertificateOfMembership *com,
+		unsigned int limit,
+		uint64_t now,
+		const MulticastGroup &mg,
+		const MAC &src,
+		unsigned int etherType,
+		const void *data,
+		unsigned int len);
 
 	/**
 	 * Clean up and resort database

+ 4 - 2
node/OutboundMulticast.cpp

@@ -28,10 +28,11 @@
 #include "Constants.hpp"
 #include "OutboundMulticast.hpp"
 #include "Switch.hpp"
+#include "CertificateOfMembership.hpp"
 
 namespace ZeroTier {
 
-void OutboundMulticast::init(uint64_t timestamp,const Address &self,uint64_t nwid,unsigned int gatherLimit,const MAC &src,const MulticastGroup &dest,unsigned int etherType,const void *payload,unsigned int len)
+void OutboundMulticast::init(uint64_t timestamp,const Address &self,uint64_t nwid,const CertificateOfMembership *com,unsigned int gatherLimit,const MAC &src,const MulticastGroup &dest,unsigned int etherType,const void *payload,unsigned int len)
 {
 	_timestamp = timestamp;
 	_nwid = nwid;
@@ -41,8 +42,9 @@ void OutboundMulticast::init(uint64_t timestamp,const Address &self,uint64_t nwi
 	_packet.setSource(self);
 	_packet.setVerb(Packet::VERB_MULTICAST_FRAME);
 	_packet.append((uint64_t)nwid);
-	_packet.append((char)0); // 0 flags
+	_packet.append((uint8_t)((com) ? 0x01 : 0x00));
 	_packet.append((uint32_t)gatherLimit); // gather limit -- set before send, start with 0
+	if (com) com->serialize(_packet);
 	_packet.append((uint32_t)dest.adi());
 	dest.mac().appendTo(_packet);
 	src.appendTo(_packet);

+ 13 - 1
node/OutboundMulticast.hpp

@@ -42,6 +42,7 @@
 namespace ZeroTier {
 
 class Switch;
+class CertificateOfMembership;
 
 /**
  * An outbound multicast packet
@@ -64,6 +65,7 @@ public:
 	 * @param timestamp Creation time
 	 * @param self My ZeroTier address
 	 * @param nwid Network ID
+	 * @param com Certificate of membership to attach or NULL to omit
 	 * @param gatherLimit Number to lazily/implicitly gather with this frame or 0 for none
 	 * @param src Source MAC address of frame
 	 * @param dest Destination multicast group (MAC + ADI)
@@ -72,7 +74,17 @@ public:
 	 * @param len Length of data
 	 * @throws std::out_of_range Data too large to fit in a MULTICAST_FRAME
 	 */
-	void init(uint64_t timestamp,const Address &self,uint64_t nwid,unsigned int gatherLimit,const MAC &src,const MulticastGroup &dest,unsigned int etherType,const void *payload,unsigned int len);
+	void init(
+		uint64_t timestamp,
+		const Address &self,
+		uint64_t nwid,
+		const CertificateOfMembership *com,
+		unsigned int gatherLimit,
+		const MAC &src,
+		const MulticastGroup &dest,
+		unsigned int etherType,
+		const void *payload,
+		unsigned int len);
 
 	/**
 	 * @return Multicast creation time

+ 70 - 46
node/Packet.hpp

@@ -148,6 +148,10 @@
 
 // Field incides for parsing verbs -------------------------------------------
 
+// Some verbs have variable-length fields. Those aren't fully defined here
+// yet-- instead they are parsed using relative indexes in IncomingPacket.
+// See their respective handler functions.
+
 #define ZT_PROTO_VERB_HELLO_IDX_PROTOCOL_VERSION (ZT_PACKET_IDX_PAYLOAD)
 #define ZT_PROTO_VERB_HELLO_IDX_MAJOR_VERSION (ZT_PROTO_VERB_HELLO_IDX_PROTOCOL_VERSION + 1)
 #define ZT_PROTO_VERB_HELLO_IDX_MINOR_VERSION (ZT_PROTO_VERB_HELLO_IDX_MAJOR_VERSION + 1)
@@ -188,40 +192,41 @@
 #define ZT_PROTO_VERB_EXT_FRAME_LEN_ETHERTYPE 2
 #define ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD (ZT_PROTO_VERB_EXT_FRAME_IDX_ETHERTYPE + ZT_PROTO_VERB_EXT_FRAME_LEN_ETHERTYPE)
 
-#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_DEPTH (ZT_PACKET_IDX_PAYLOAD)
-#define ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_DEPTH 2
-#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_FIFO (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_DEPTH + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_DEPTH)
-#define ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_FIFO 320
-#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_FIFO + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_FIFO)
-#define ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_BLOOM 1024
-#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_BLOOM)
-#define ZT_PROTO_VERB_MULTICAST_FRAME_LEN_FLAGS 1
-#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS)
-#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_FLAGS)
-#define ZT_PROTO_VERB_MULTICAST_FRAME_LEN_NETWORK_ID 8
-#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM_NONCE (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_NETWORK_ID)
-#define ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_BLOOM_NONCE 2
-#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX_BITS (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM_NONCE + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_BLOOM_NONCE)
-#define ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_PREFIX_BITS 1
-#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX_BITS + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_PREFIX_BITS)
-#define ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_PREFIX 1
-#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ORIGIN (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_PREFIX)
-#define ZT_PROTO_VERB_MULTICAST_FRAME_LEN_ORIGIN 5
-#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ORIGIN_MCID (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ORIGIN + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_ORIGIN)
-#define ZT_PROTO_VERB_MULTICAST_FRAME_LEN_ORIGIN_MCID 3
-#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_GUID (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ORIGIN)
-#define ZT_PROTO_VERB_MULTICAST_FRAME_LEN_GUID 8
-#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ORIGIN_MCID + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_ORIGIN_MCID)
-#define ZT_PROTO_VERB_MULTICAST_FRAME_LEN_SOURCE_MAC 6
-#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_MAC (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_SOURCE_MAC)
-#define ZT_PROTO_VERB_MULTICAST_FRAME_LEN_DEST_MAC 6
-#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_ADI (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_MAC + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_DEST_MAC)
-#define ZT_PROTO_VERB_MULTICAST_FRAME_LEN_DEST_ADI 4
-#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_ADI + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_DEST_ADI)
-#define ZT_PROTO_VERB_MULTICAST_FRAME_LEN_ETHERTYPE 2
-#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME_LEN (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_ETHERTYPE)
-#define ZT_PROTO_VERB_MULTICAST_FRAME_LEN_FRAME_LEN 2
-#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME_LEN + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_FRAME_LEN)
+// P5_MULTICAST_FRAME is deprecated
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_DEPTH (ZT_PACKET_IDX_PAYLOAD)
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_PROPAGATION_DEPTH 2
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_FIFO (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_DEPTH + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_DEPTH)
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_PROPAGATION_FIFO 320
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_FIFO + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_FIFO)
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_PROPAGATION_BLOOM 1024
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_FLAGS (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_BLOOM)
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_FLAGS 1
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS)
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_NETWORK_ID (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_FLAGS)
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_NETWORK_ID 8
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM_NONCE (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_NETWORK_ID)
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_PROPAGATION_BLOOM_NONCE 2
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX_BITS (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM_NONCE + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_BLOOM_NONCE)
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_PROPAGATION_PREFIX_BITS 1
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX_BITS + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_PREFIX_BITS)
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_PROPAGATION_PREFIX 1
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_ORIGIN (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_PREFIX)
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_ORIGIN 5
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_ORIGIN_MCID (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ORIGIN + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_ORIGIN)
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_ORIGIN_MCID 3
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_GUID (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ORIGIN)
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_GUID 8
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_SOURCE_MAC (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ORIGIN_MCID + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_ORIGIN_MCID)
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_SOURCE_MAC 6
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_DEST_MAC (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_SOURCE_MAC)
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_DEST_MAC 6
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_DEST_ADI (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_MAC + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_DEST_MAC)
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_DEST_ADI 4
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_ETHERTYPE (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_ADI + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_DEST_ADI)
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_ETHERTYPE 2
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_FRAME_LEN (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_ETHERTYPE)
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_FRAME_LEN 2
+#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_FRAME (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME_LEN + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_FRAME_LEN)
 
 #define ZT_PROTO_VERB_MULTICAST_FRAME_FLAGS_HAS_MEMBERSHIP_CERTIFICATE 0x01
 
@@ -229,6 +234,18 @@
 #define ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN (ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID + 8)
 #define ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT (ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN + 2)
 
+#define ZT_PROTO_VERB_MULTICAST_GATHER_IDX_NETWORK_ID (ZT_PACKET_IDX_PAYLOAD)
+#define ZT_PROTO_VERB_MULTICAST_GATHER_IDX_FLAGS (ZT_PROTO_VERB_MULTICAST_GATHER_IDX_NETWORK_ID + 8)
+#define ZT_PROTO_VERB_MULTICAST_GATHER_IDX_MAC (ZT_PROTO_VERB_MULTICAST_GATHER_IDX_FLAGS + 1)
+#define ZT_PROTO_VERB_MULTICAST_GATHER_IDX_ADI (ZT_PROTO_VERB_MULTICAST_GATHER_IDX_MAC + 6)
+#define ZT_PROTO_VERB_MULTICAST_GATHER_IDX_GATHER_LIMIT (ZT_PROTO_VERB_MULTICAST_GATHER_IDX_ADI + 4)
+#define ZT_PROTO_VERB_MULTICAST_GATHER_IDX_COM (ZT_PROTO_VERB_MULTICAST_GATHER_IDX_GATHER_LIMIT + 4)
+
+#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID (ZT_PACKET_IDX_PAYLOAD)
+#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID + 8)
+#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_GATHER_LIMIT (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS + 1)
+// remainder are relative to offset after COM -- might do this with macros at some point
+
 #define ZT_PROTO_VERB_HELLO__OK__IDX_TIMESTAMP (ZT_PROTO_VERB_OK_IDX_PAYLOAD)
 #define ZT_PROTO_VERB_HELLO__OK__IDX_PROTOCOL_VERSION (ZT_PROTO_VERB_HELLO__OK__IDX_TIMESTAMP + 8)
 #define ZT_PROTO_VERB_HELLO__OK__IDX_MAJOR_VERSION (ZT_PROTO_VERB_HELLO__OK__IDX_PROTOCOL_VERSION + 1)
@@ -665,16 +682,20 @@ public:
 		 *   <[6] MAC address of multicast group being queried>
 		 *   <[4] 32-bit ADI for multicast group being queried>
 		 *   <[4] 32-bit (suggested) max number of multicast peers desired or 0 for no limit>
-		 *  [<[...] network membership certificate (optional)>]
+		 *  [<[...] network certificate of membership if included>]
 		 *
-		 * Flags are:
-		 *   0x01 - network membership certificate is included
+		 * Flags:
+		 *   0x01 - Network certificate of membership is attached
 		 *
 		 * This message asks a peer for additional known endpoints that have
 		 * LIKEd a given multicast group. It's sent when the sender wishes
 		 * to send multicast but does not have the desired number of recipient
 		 * peers.
 		 *
+		 * A certificate of network membership can be included so that peers
+		 * can check network membership before responding. Without certificate
+		 * check any peer could probe multicast memberships on any network.
+		 *
 		 * OK response payload:
 		 *   <[8] 64-bit network ID>
 		 *   <[6] MAC address of multicast group being queried>
@@ -698,27 +719,30 @@ public:
 
 		/* Multicast frame:
 		 *   <[8] 64-bit network ID>
-		 *   <[1] flags (currently unused, must be 0)>
-		 *   <[4] 32-bit (suggested) gather limit or 0 for no gathering>
+		 *   <[1] flags>
+		 *   <[4] 32-bit (suggested) gather limit or 0 for no implicit gathering>
+		 *  [<[...] network certificate of membership if included>]
 		 *   <[4] 32-bit multicast ADI (note that this is out of order here -- it precedes MAC)>
 		 *   <[6] destination MAC or all zero for destination node>
 		 *   <[6] source MAC or all zero for node of origin>
 		 *   <[2] 16-bit ethertype>
 		 *   <[...] ethernet payload>
 		 *
+		 * Flags:
+		 *   0x01 - Network certificate of membership is attached
+		 *
 		 * This is similar to EXT_FRAME but carries a multicast, and is sent
-		 * out to recipients on a multicast list.
+		 * out to recipients on a multicast list. It may also specify a desired
+		 * number of multicast peers to gather, which is called "implicit
+		 * gathering." It is only allowed if certificate authentication permits
+		 * these peers to communicate on this network.
 		 *
 		 * (ADI precedes MAC here so that everything from destination MAC forward
 		 * could be treated as a raw Ethernet frame.)
 		 *
 		 * OK response payload:
-		 *   <[1] flags>
-		 *   [... same as OK(GATHER) if flag 0x01 is set ...]
-		 *
-		 * Flags in OK are 0x01 for "gathering results returned," which can be
-		 * sent if a gather limit is specified in the original FRAME and there
-		 * are known endpoints to gather. This way frames can also gather.
+		 *   <[1] flags, 0x01 if implicit gathering results are included>
+		 *   [... same as OK(MULTICAST_GATHER) payload if flag 0x01 is set ...]
 		 *
 		 * ERROR response payload:
 		 *   <[6] multicast group MAC>