// tries to parse the specified chunk of bytes as a multicast policy packet. If it can, // it returns a managed representation. Otherwise, it returns null. public static MulticastPolicyPacket Parse(byte[] buffer, int offset, int count) { if (buffer == null) { throw new ArgumentNullException("buffer"); } if (offset < 0 || offset > buffer.Length) { throw new ArgumentOutOfRangeException("offset"); } if (count < 0 || count > (buffer.Length - offset)) { throw new ArgumentOutOfRangeException("count"); } if (count < ConstantLength) { // malformed packet - not long enough even if both variable-length fields are empty return null; } if (buffer[offset] != HeaderBytes[0] || buffer[offset + 1] != HeaderBytes[1] || buffer[offset + 2] != HeaderBytes[2]) { // malformed packet - doesn't have the header return null; } if (buffer[offset + 3] != 1) { // we only understand version 1 of the protocol - ignore anything using a newer version. return null; } MulticastPolicyPacket rval = new MulticastPolicyPacket(); rval.type = (MulticastPolicyPacketType)buffer[offset + 4]; rval.messageId[0] = buffer[offset + 5]; rval.messageId[1] = buffer[offset + 6]; rval.messageId[2] = buffer[offset + 7]; rval.messageId[3] = buffer[offset + 8]; rval.port = ((int)buffer[offset + 9]) | (((int)buffer[offset + 10]) << 8); int applicationOriginLength = (buffer[offset + 11]) | (buffer[offset + 12] << 8); int groupAddressLength = buffer[offset + 13]; offset += 14; if ((offset + applicationOriginLength) > count) { // malformed packet - application origin length past the end of the buffer return null; } rval.applicationOriginBytes = new byte[applicationOriginLength]; Buffer.BlockCopy(buffer, offset, rval.applicationOriginBytes, 0, applicationOriginLength); try { UTF8Encoding encoding = new UTF8Encoding(false, true); rval.applicationOrigin = encoding.GetString(rval.applicationOriginBytes, 0, applicationOriginLength); } catch (DecoderFallbackException) { // malformed packet - invalid UTF8 in application origin uri return null; } offset += applicationOriginLength; if ((offset + groupAddressLength) > count) { // malformed packet - group address length past the end of the buffer return null; } if (groupAddressLength != 4 && groupAddressLength != 16) { // malformed packet - group address isn't ipv4 or ipv6 return null; } rval.groupAddressBytes = new byte[groupAddressLength]; Buffer.BlockCopy(buffer, offset, rval.groupAddressBytes, 0, groupAddressLength); rval.groupAddress = new IPAddress(rval.groupAddressBytes); return rval; }
private bool ProcessSingleSourceAnnouncement(MulticastPolicyPacket packet, EndPoint source) { bool async = false; Trace.TraceInformation("MulticastPolicyServerCore<" + addressFamily + ">: " + "Processing packet with GroupAddress=" + packet.GroupAddress + ", Port=" + packet.Port + ", ApplicationOrigin=" + packet.ApplicationOrigin); if (ShouldRespondToPacket(packet, configuration.InternalSingleSourceConfiguration)) { packet.Type = MulticastPolicyPacketType.Authorization; int packetLength = packet.SerializeTo(buffer, 0, buffer.Length); IAsyncResult result; try { result = socket.BeginSendTo(buffer, 0, packetLength, SocketFlags.None, source, SendCompletionCallback, null); } catch (SocketException ex) { Trace.TraceWarning("MulticastPolicyServerCore<{0}>: Error while sending authorization packet: {1}", addressFamily, ex); return false; } async = !(result.CompletedSynchronously); if (!async) { ProcessSendCompletion(result, false); } } return async; }
private bool ShouldRespondToPacket(MulticastPolicyPacket packet, PrefixKeyedDictionary<MulticastResource> config) { ICollection<MulticastResource> allowedResources = null; if (!config.TryGetValueByPrefixMatch(packet.ApplicationOrigin, out allowedResources)) { Trace.TraceInformation( "MulticastPolicyServerCore<{0}>: Rejecting because the app is blocked entirely", addressFamily); return false; } foreach (MulticastResource resource in allowedResources) { if ((resource.GroupAddress == IPAddress.Any || IPAddress.Equals(resource.GroupAddress, packet.GroupAddress)) && (resource.HighPort >= packet.Port && resource.LowPort <= packet.Port)) { Trace.TraceInformation( "MulticastPolicyServerCore<{0}>: Access is allowed, sending authorization packet", addressFamily); return true; } } Trace.TraceInformation( "MulticastPolicyServerCore<{0}>: Rejecting because the app is requesting access to an unapproved group/port", addressFamily); return false; }
private bool ProcessPacket(MulticastPolicyPacket packet, EndPoint source, IPPacketInformation packetInfo) { if (packet == null) { return false; } if (packet.Type != MulticastPolicyPacketType.Announcement) { return false; } bool async; if (IsMulticastAddress(packetInfo.Address)) { async = ProcessAnySourceAnnouncement(packet, packetInfo); } else { async = ProcessSingleSourceAnnouncement(packet, source); } return async; }