public void SendToRaw(IPAddress rawAddress, byte id, byte[] buf, int offset, int size) { var headerList = new ArrayList(); var icmpHeader = new IcmpHeader(); icmpHeader.Id = 123; icmpHeader.Sequence = 24; icmpHeader.Type = IcmpHeader.EchoReplyType; icmpHeader.Code = IcmpHeader.EchoReplyCode; headerList.Add(icmpHeader); var myheader = new MyProtocol(); myheader.Id = (byte)(byte.MaxValue - id); headerList.Add(myheader); byte[] sub = new byte[size]; Array.Copy(buf, offset, sub, 0, size); var rawpacket = ProtocolHeader.BuildPacket(headerList, sub); RawSocket.BeginSendTo(rawpacket, 0, rawpacket.Length, SocketFlags.None, new IPEndPoint(rawAddress, 0), new AsyncCallback(TransportLayer.Instance().OnRawWriteComplete), rawpacket.Length); }
private void OnRawReadComplete(IAsyncResult ia) { byte[] buf = (byte[])ia.AsyncState; int readed = RawSocket.EndReceive(ia); if (readed <= PAYLOAD_OFFSET_IP_HEADER) { Log.D("raw bytes {0} <= ip+icmp header length,removed", readed); return; } var ipLength = (ushort)(buf[2] * 256 + buf[3]); var srcAddr = new IPAddress(new byte[] { buf[12], buf[13], buf[14], buf[15] }); var icmpWithPayloadLength = ipLength - Ipv4Header.Ipv4HeaderLength; Log.D("receiving from {0} ,icmp with payload should be {1} bytes", srcAddr, icmpWithPayloadLength); //now buf contains whole packet ushort checksum = IcmpHeader.ComputeChecksum(buf, Ipv4Header.Ipv4HeaderLength, icmpWithPayloadLength); if (checksum != 0) { Log.E("icmp checksum {0} error, removed", checksum); //invalid pack return; } var crc = new Crc(); var payloadLength = ipLength - PAYLOAD_OFFSET_IP_HEADER; byte crc8 = crc.Update(buf, MY_HEADER_OFFSET_IP_HEADER + 1, payloadLength + 1); byte packetCrc8 = buf[MY_HEADER_OFFSET_IP_HEADER]; if (crc8 != packetCrc8) { Log.E("calced crc {0}!= {1} failed, removed", crc8, packetCrc8); return; } // all ok foreach (var l in Listeners) { l.OnRawRead(srcAddr, buf[MY_HEADER_OFFSET_IP_HEADER + 1], buf, PAYLOAD_OFFSET_IP_HEADER, payloadLength); } }
/// <summary> /// This routine creates an instance of the IcmpHeader class from a byte /// array that is a received IGMP packet. This is useful when a packet /// is received from the network and the header object needs to be /// constructed from those values. /// </summary> /// <param name="icmpPacket">Byte array containing the binary ICMP header</param> /// <param name="bytesCopied">Number of bytes used in header</param> /// <returns>Returns the IcmpHeader object created from the byte array</returns> static public IcmpHeader Create(byte[] icmpPacket, ref int bytesCopied) { IcmpHeader icmpHeader = new IcmpHeader(); int offset = 0; // Make sure byte array is large enough to contain an ICMP header if (icmpPacket.Length < IcmpHeader.IcmpHeaderLength) { return(null); } icmpHeader.icmpType = icmpPacket[offset++]; icmpHeader.icmpCode = icmpPacket[offset++]; icmpHeader.icmpChecksum = BitConverter.ToUInt16(icmpPacket, offset); offset += 2; icmpHeader.icmpId = BitConverter.ToUInt16(icmpPacket, offset); offset += 2; icmpHeader.icmpSequence = BitConverter.ToUInt16(icmpPacket, offset); bytesCopied = IcmpHeader.IcmpHeaderLength; return(icmpHeader); }