/** * This handles the packet forwarding protocol */ public void HandleData(MemBlock b, ISender ret_path, object state) { /* * Check it */ AHSender ahs = ret_path as AHSender; if( ahs != null ) { //This was an AHSender: /* * This goes A -> B -> C */ if( b[0] == 0 ) { int offset = 1; //This is the first leg, going from A->B Address add_c = AddressParser.Parse(b.Slice(offset, Address.MemSize)); offset += Address.MemSize; //Since ahs a sender to return, we would be the source: Address add_a = ahs.Destination; short ttl = NumberSerializer.ReadShort(b, offset);//2 bytes offset += 2; ushort options = (ushort) NumberSerializer.ReadShort(b, offset);//2 bytes offset += 2; MemBlock payload = b.Slice(offset); MemBlock f_header = MemBlock.Reference( new byte[]{1} ); /* * switch the packet from [A B f0 C] to [B C f 1 A] */ ICopyable new_payload = new CopyList(PType.Protocol.Forwarding, f_header, add_a, payload); /* * ttl and options are present in the forwarding header. */ AHSender next = new AHSender(_n, ahs.ReceivedFrom, add_c, ttl, options); next.Send(new_payload); } else if ( b[0] == 1 ) { /* * This is the second leg: B->C * Make a Forwarding Sender, and unwrap the inside packet */ Address add_a = AddressParser.Parse(b.Slice(1, Address.MemSize)); Address add_b = ahs.Destination; MemBlock rest_of_payload = b.Slice(1 + Address.MemSize); //Here's the return path: ISender new_ret_path = new ForwardingSender(_n, add_b, add_a); _n.HandleData(rest_of_payload, new_ret_path, this); } } else { //This is not (currently) supported. Console.Error.WriteLine("Got a forwarding request from: {0}", ret_path); } }
public ARPPacket(int HardwareType, int ProtocolType, Operations Operation, MemBlock SenderHWAddress, MemBlock SenderProtoAddress, MemBlock TargetHWAddress, MemBlock TargetProtoAddress) { byte[] header = new byte[8]; NumberSerializer.WriteUShort((ushort) HardwareType, header, 0); NumberSerializer.WriteUShort((ushort) ProtocolType, header, 2); header[4] = (byte) SenderHWAddress.Length; header[5] = (byte) SenderProtoAddress.Length; NumberSerializer.WriteUShort((ushort) Operation, header, 6); _icpacket = new CopyList(MemBlock.Reference(header), SenderHWAddress, SenderProtoAddress, TargetHWAddress, TargetProtoAddress); }
/** <summary>Takes in the IP Header fields and a payload to create an IP Packet. Unlisted fields are generated by this constructor automatically. </summary> <param name="Protocol">The type of payload</param> <param name="SourceIP">The packets originating ip address</param> <param name="DestinationIP">The destination for the packet</param> <param name="hdr">The original header of the IPPacket</param> <param name="Payload">The data stored in the IP Packet</param> */ public IPPacket(Protocols Protocol, MemBlock SourceIP, MemBlock DestinationIP, MemBlock hdr, ICopyable Payload) { byte[] header = new byte[20]; // Version | IHL header[0] = hdr[0]; // Just a routine header! header[1] = hdr[1]; int length = header.Length + Payload.Length; header[2] = (byte) ((length >> 8) & 0xFF); header[3] = (byte) (length & 0xFF); // Fragment crap header[4] = hdr[4]; header[5] = hdr[5]; header[6] = hdr[6]; header[7] = hdr[7]; // TTL header[8] = hdr[8]; header[9] = hdr[9]; for(int i = 0; i < 4; i++) { header[12 + i] = SourceIP[i]; header[16 + i] = DestinationIP[i]; } int checksum = GenerateChecksum(MemBlock.Reference(header)); header[10] = (byte) ((checksum >> 8) & 0xFF); header[11] = (byte) (checksum & 0xFF); MemBlock Header = MemBlock.Reference(header); _icpacket = new CopyList(Header, Payload); this.Protocol = Protocol; this.SourceIP = SourceIP; this.DestinationIP = DestinationIP; _icpayload = Payload; }
/** <summary>Constructor when creating a DNS Query</summary> <param name="QNAME">the name of resource you are looking up, IP Address when QTYPE = PTR otherwise hostname</param> <param name="QTYPE"> the type of look up to perform</param> <param name="QCLASS">should always be IN</param> */ public Question(String QNAME, DNSPacket.TYPES QTYPE, DNSPacket.CLASSES QCLASS) { this.QNAME = QNAME; this.QTYPE = QTYPE; this.QCLASS = QCLASS; if(QTYPE == DNSPacket.TYPES.A) { QNAME_BLOB = DNSPacket.HostnameStringToMemBlock(QNAME); } else if(QTYPE == DNSPacket.TYPES.PTR) { QNAME_BLOB = DNSPacket.PtrStringToMemBlock(QNAME); } else { throw new Exception("Invalid QTYPE: " + QTYPE + "!"); } // 2 for QTYPE + 2 for QCLASS byte[] data = new byte[4]; int idx = 0; data[idx++] = (byte) ((((int) QTYPE) >> 8) & 0xFF); data[idx++] = (byte) (((int) QTYPE) & 0xFF); data[idx++] = (byte) ((((int) QCLASS) >> 8) & 0xFF); data[idx++] = (byte) (((int) QCLASS) & 0xFF); _icpacket = new CopyList(QNAME_BLOB, MemBlock.Reference(data)); }
/// <summary>After a restart of the Security system, one guy may think /// we still have an association and there will be no way for him to know /// that our side is broken, unless we notify him as such. We notify him /// by sending this packet. How he deals with that is up to him.</summary> protected void NoSuchSA(int spi, ISender remote_sender) { SecurityControlMessage scm_reply = new SecurityControlMessage(); scm_reply.Version = Version; scm_reply.SPI = spi; scm_reply.Type = SecurityControlMessage.MessageType.NoSuchSA; ICopyable to_send = new CopyList(Security, SecureControl, scm_reply.Packet); remote_sender.Send(to_send); }
/// <summary>Creates an Ethernet Packet from Ethernet fields and the payload</summary> /// <param name="DestinationAddress">Where the Ethernet packet is going.</param> /// <param name="SourceAddress">Where the Ethernet packet originated.</param> /// <param name="Type">Type of Ethernet payload.</param> /// <param name="Payload">Payload as an ICopyable</param> public EthernetPacket(MemBlock DestinationAddress, MemBlock SourceAddress, Types Type, ICopyable Payload) { byte[] header = new byte[14]; for(int i = 0; i < 6; i++) { header[i] = DestinationAddress[i]; header[6 + i] = SourceAddress[i]; } header[12] = (byte) (((int) Type >> 8) & 0xFF); header[13] = (byte) ((int) Type & 0xFF); _icpacket = new CopyList(MemBlock.Reference(header), Payload); _icpayload = Payload; this.DestinationAddress = DestinationAddress; this.SourceAddress = SourceAddress; this.Type = Type; }
public DHCPPacket(byte op, MemBlock xid, MemBlock ciaddr, MemBlock yiaddr, MemBlock siaddr, MemBlock chaddr, Dictionary<OptionTypes, MemBlock> Options) { this.op = op; this.xid = xid; this.ciaddr = ciaddr; this.yiaddr = yiaddr; this.siaddr = siaddr; this.chaddr = chaddr; this.Options = Options; byte[] header = new byte[240]; header[0] = op; header[1] = 1; header[2] = (byte) chaddr.Length; header[3] = 0; xid.CopyTo(header, 4); for(int i = 8; i < 12; i++) { header[i] = 0; } ciaddr.CopyTo(header, 12); yiaddr.CopyTo(header, 16); siaddr.CopyTo(header, 20); for(int i = 24; i < 28; i++) { header[i] = 0; } chaddr.CopyTo(header, 28); for(int i = 34; i < 236; i++) { header[i] = 0; } magic_key.CopyTo(header, 236); _icpacket = new CopyList(MemBlock.Reference(header)); foreach(KeyValuePair<OptionTypes, MemBlock> kvp in Options) { MemBlock value = kvp.Value; byte[] tmp = new byte[2]; tmp[0] = (byte) kvp.Key; tmp[1] = (byte) value.Length; _icpacket = new CopyList(_icpacket, MemBlock.Reference(tmp), value); } byte []end = new byte[1]{255}; /* End of Options */ _icpacket = new CopyList(_icpacket, MemBlock.Reference(end)); }
/** * Abandon any attempts to get requests for the given ID. * @throw Exception if handler is not the original handler for this Request */ public void StopRequest(int request_id, IReplyHandler handler) { RequestState rs = null; lock( _sync ) { rs = (RequestState)_req_state_table[request_id]; if( rs != null ) { if( rs.ReplyHandler != handler ) { throw new Exception( String.Format("Handler mismatch: {0} != {1}", handler, rs.ReplyHandler)); } _req_state_table.Remove( request_id ); } } if( rs != null ) { /* * Send an ack for this reply: */ byte[] ack_payload = new byte[5]; ack_payload[0] = (byte)ReqrepType.ReplyAck; NumberSerializer.WriteInt(request_id, ack_payload, 1); ICopyable data = new CopyList(PType.Protocol.ReqRep, MemBlock.Reference(ack_payload)); foreach(ISender ret_path in rs.Repliers) { try { //Try to send an ack, but if we can't, oh well... ret_path.Send(data); } catch { } } } }
/** * Creates the tunnel header attached in front of packet sent on the tunnnel edge. * We have to make this everytime _remote_id changes. * @param local_id local id of the edge. * @param remote_id remote id of the edge. * @param source local node address. * @param target target node address. */ protected static ICopyable GetTunnelHeader(int local_id, int remote_id, Address source, Address target) { //The header always stays fixed for this TunnelEdge byte[] ids = new byte[9]; ids[0] = (byte) TunnelEdgeListener.MessageType.EdgeData; //Write the IDs of the edge: //[edge data][local id 4 bytes][remote id 4 bytes][packet] NumberSerializer.WriteInt(local_id, ids, 1); NumberSerializer.WriteInt(remote_id, ids, 5); MemBlock ids_mb = MemBlock.Reference( ids ); ICopyable header = new CopyList( PType.Protocol.AH, new AHHeader(1, 2, source, target, AHPacket.AHOptions.Exact), PType.Protocol.Tunneling, ids_mb ); //Now we have assembled the full header to prepend to any data, but //it is a waste to do all the copying each time, so we copy it into //one buffer now: return MemBlock.Copy( (ICopyable) header ); }
/** <summary>Creates a DNS packet from the parameters provided.</summary> <param name="ID">A unique ID for the packet, responses should be the same as the query</param> <param name="QUERY">True if a query, false if a response</param> <param name="OPCODE">0 = Query, which is the only supported parsing method </param> <param name="AA">Authoritative Answer, true if there is a resolution for the lookup.</param> <param name="Questions">A list of Questions.</param> <param name="Answers">A list of Answers.</param> */ public DNSPacket(short ID, bool QUERY, byte OPCODE, bool AA, bool RA, bool RD, Question[] Questions, Response[] Answers, Response[] Authority, Response[] Additional) { byte[] header = new byte[12]; this.ID = ID; header[0] = (byte) ((ID >> 8) & 0xFF); header[1] = (byte) (ID & 0xFF); this.QUERY = QUERY; if(!QUERY) { header[2] |= 0x80; } this.OPCODE = OPCODE; header[2] |= (byte) (OPCODE << 3); this.AA = AA; if(AA) { header[2] |= 0x4; } this.RD = RD; if(RD) { header[2] |= 0x1; } this.RA = RA; if(RA) { header[3] |= 0x80; } if(Questions != null) { this.Questions = Questions; header[4] = (byte) ((Questions.Length >> 8) & 0xFF); header[5] = (byte) (Questions.Length & 0xFF); } else { this.Questions = new Question[0]; header[4] = 0; header[5] = 0; } if(Answers != null) { this.Answers = Answers; header[6] = (byte) ((Answers.Length >> 8) & 0xFF); header[7] = (byte) (Answers.Length & 0xFF); } else { this.Answers = new Response[0]; header[6] = 0; header[7] = 0; } if(Authority != null) { this.Authority = Authority; header[8] = (byte) ((Authority.Length >> 8) & 0xFF); header[9] = (byte) (Authority.Length & 0xFF); } else { this.Authority = new Response[0]; header[8] = 0; header[9] = 0; } if(Additional != null) { this.Additional = Additional; header[10] = (byte) ((Additional.Length >> 8) & 0xFF); header[11] = (byte) (Additional.Length & 0xFF); } else { this.Additional = new Response[0]; header[10] = 0; header[11] = 0; } _icpacket = MemBlock.Reference(header); for(int i = 0; i < this.Questions.Length; i++) { _icpacket = new CopyList(_icpacket, Questions[i].ICPacket); } for(int i = 0; i < this.Answers.Length; i++) { _icpacket = new CopyList(_icpacket, Answers[i].ICPacket); } for(int i = 0; i < this.Authority.Length; i++) { _icpacket = new CopyList(_icpacket, Authority[i].ICPacket); } for(int i = 0; i < this.Additional.Length; i++) { _icpacket = new CopyList(_icpacket, Additional[i].ICPacket); } }
/// <summary>3b) Receive a Confirm, verify the entire stack and send a Confirm /// 4a)Receive a Confirm, verify the entire stack and all set to go</summary> /// <param name="sa">A security association that we wish to perform the /// specified control operation on.</param> /// <param name="scm">The received SecurityControlMessage.</param> /// <param name="scm_reply">A prepared reply message (with headers and such.</param> /// <param name="return_path">Where to send the result.</param> /// <param name="low_level_sender">We expect the return_path to not be an edge or /// some other type of "low level" sender, so this contains the parsed out value.</param> protected void HandleControlConfirm(SecurityAssociation sa, SecurityControlMessage scm, SecurityControlMessage scm_reply, ISender return_path, ISender low_level_sender) { ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Received Confirm from: " + low_level_sender); if(sa == null) { throw new Exception("No valid SA!"); } HashAlgorithm sha1 = new SHA1CryptoServiceProvider(); scm.Verify((RSACryptoServiceProvider) sa.RemoteCertificate.Value.RSA, sha1); if(return_path == low_level_sender) { sa.VerifyResponse(scm.Hash); } else { sa.VerifyRequest(scm.Hash); scm_reply.LocalCookie = scm.RemoteCookie; scm_reply.RemoteCookie = scm.LocalCookie; scm_reply.Hash = sa.DHEWithCertificateAndCAsInHash.Value; scm_reply.Type = SecurityControlMessage.MessageType.Confirm; lock(_private_key_lock) { scm_reply.Sign(_private_key, sha1); } ICopyable to_send = new CopyList(SecureControl, scm_reply.Packet); return_path.Send(to_send); } if(Verify(sa)) { sa.Enable(); } else { sa.Close("Unable to verify the SA as being valid!"); } ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Successful Confirm from: " + low_level_sender); }
/// <summary>3a) Receive a DHEWithCertificate, verify the certificate and DHE and /// send a Confirm that you are ready to Verify the stack and start the /// system.</summary> /// <param name="sa">A security association that we wish to perform the /// specified control operation on.</param> /// <param name="scm">The received SecurityControlMessage.</param> /// <param name="scm_reply">A prepared reply message (with headers and such.</param> /// <param name="return_path">Where to send the result.</param> /// <param name="low_level_sender">We expect the return_path to not be an edge or /// some other type of "low level" sender, so this contains the parsed out value.</param> protected void HandleControlDHEWithCertificates(SecurityAssociation sa, SecurityControlMessage scm, SecurityControlMessage scm_reply, ISender return_path, ISender low_level_sender) { ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Received DHEWithCertificate from: " + low_level_sender); if(sa == null) { throw new Exception("No valid SA!"); } byte[] cert = new byte[scm.Certificate.Length]; scm.Certificate.CopyTo(cert, 0); X509Certificate rcert = new X509Certificate(cert); HashAlgorithm sha1 = new SHA1CryptoServiceProvider(); scm.Verify((RSACryptoServiceProvider) rcert.RSA, sha1); _ch.Verify(rcert); sa.RemoteCertificate.Value = rcert; sa.RDHE.Value = scm.DHE; scm_reply.LocalCookie = scm.RemoteCookie; scm_reply.RemoteCookie = scm.LocalCookie; scm_reply.Hash = MemBlock.Reference(sha1.ComputeHash((byte[]) scm.Packet)); scm_reply.Type = SecurityControlMessage.MessageType.Confirm; lock(_private_key_lock) { scm_reply.Sign(_private_key, sha1); } ICopyable to_send = new CopyList(Security, SecureControl, scm_reply.Packet); _rrman.SendRequest(return_path, ReqrepManager.ReqrepType.Request, to_send, this, sa); ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Successful DHEWithCertificate from: " + low_level_sender); }
/// <summary>2b) Receive a DHEWithCertificateAndCAs, verify the certificate and attempt /// to find a matching Certificate for the list of CAs, if you find one, /// finish the DHE handshake and send the certificate via a DHEWithCertificate</summary> /// <param name="sa">A security association that we wish to perform the /// specified control operation on.</param> /// <param name="scm">The received SecurityControlMessage.</param> /// <param name="scm_reply">A prepared reply message (with headers and such.</param> /// <param name="return_path">Where to send the result.</param> /// <param name="low_level_sender">We expect the return_path to not be an edge or /// some other type of "low level" sender, so this contains the parsed out value.</param> protected void HandleControlDHEWithCertificateAndCAs(SecurityAssociation sa, SecurityControlMessage scm, SecurityControlMessage scm_reply, ISender return_path, ISender low_level_sender) { ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Received DHEWithCertificateAndCAs from: " + low_level_sender); if(sa == null) { sa = CreateSecurityAssociation(low_level_sender, scm.SPI, false); } byte[] cert = new byte[scm.Certificate.Length]; scm.Certificate.CopyTo(cert, 0); X509Certificate rcert = new X509Certificate(cert); _ch.Verify(rcert); HashAlgorithm sha1 = new SHA1CryptoServiceProvider(); scm.Verify((RSACryptoServiceProvider) rcert.RSA, sha1); X509Certificate lcert = null; if(SecurityPolicy.GetPolicy(scm.SPI).PreExchangedKeys) { lcert = _ch.DefaultCertificate; } else { lcert = _ch.FindCertificate(scm.CAs); } sa.LocalCertificate.Value = lcert; sa.RemoteCertificate.Value = rcert; sa.RDHE.Value = scm.DHE; sa.DHEWithCertificateAndCAsInHash.Value = MemBlock.Reference(sha1.ComputeHash((byte[]) scm.Packet)); scm_reply.LocalCookie = scm.RemoteCookie; scm_reply.RemoteCookie = scm.LocalCookie; scm_reply.DHE = sa.LDHE; scm_reply.Certificate = MemBlock.Reference(lcert.RawData); scm_reply.Type = SecurityControlMessage.MessageType.DHEWithCertificate; lock(_private_key_lock) { scm_reply.Sign(_private_key, sha1); } sa.DHEWithCertificateHash.Value = MemBlock.Reference(sha1.ComputeHash((byte[]) scm_reply.Packet)); ICopyable to_send = new CopyList(SecureControl, scm_reply.Packet); return_path.Send(to_send); ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Successful DHEWithCertificateAndCAs from: " + low_level_sender); }
/// <summary>2a) Receive a CookieResponse that contains a list of CAs, if you have /// a Certificate that supports one of the CAs send it along with a DHE /// and a list of your supported CAs in a DHEWithCertificateAndCAs.</summary> /// <param name="sa">A security association that we wish to perform the /// specified control operation on.</param> /// <param name="scm">The received SecurityControlMessage.</param> /// <param name="scm_reply">A prepared reply message (with headers and such.</param> /// <param name="return_path">Where to send the result.</param> /// <param name="low_level_sender">We expect the return_path to not be an edge or /// some other type of "low level" sender, so this contains the parsed out value.</param> protected void HandleControlCookieResponse(SecurityAssociation sa, SecurityControlMessage scm, SecurityControlMessage scm_reply, ISender return_path, ISender low_level_sender) { ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Received CookieResponse from: " + low_level_sender); if(sa == null) { throw new Exception("No valid SA!"); } // This seems like unnecessary code scm_reply.Type = SecurityControlMessage.MessageType.CookieResponse; X509Certificate lcert = null; if(SecurityPolicy.GetPolicy(scm.SPI).PreExchangedKeys) { lcert = _ch.DefaultCertificate; } else { lcert = _ch.FindCertificate(scm.CAs); } sa.RemoteCookie.Value = scm.LocalCookie; sa.LocalCertificate.Value = lcert; scm_reply.Certificate = lcert.RawData; scm_reply.DHE = sa.LDHE; scm_reply.LocalCookie = scm.RemoteCookie; scm_reply.RemoteCookie = scm.LocalCookie; scm_reply.Type = SecurityControlMessage.MessageType.DHEWithCertificateAndCAs; if(SecurityPolicy.GetPolicy(scm.SPI).PreExchangedKeys) { scm_reply.CAs = new List<MemBlock>(0); } else { scm_reply.CAs = _ch.SupportedCAs; } HashAlgorithm sha1 = new SHA1CryptoServiceProvider(); lock(_private_key_lock) { scm_reply.Sign(_private_key, sha1); } sa.DHEWithCertificateAndCAsOutHash.Value = sha1.ComputeHash((byte[]) scm_reply.Packet); ICopyable to_send = new CopyList(Security, SecureControl, scm_reply.Packet); _rrman.SendRequest(return_path, ReqrepManager.ReqrepType.Request, to_send, this, sa); ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Successful CookieResponse from: " + low_level_sender); }
/// <summary>1b) Receive a Cookie which responds with a CookieResponse</summary> /// <param name="sa">A security association that we wish to perform the /// specified control operation on.</param> /// <param name="calc_cookie">Cookie value for the association sender.</param> /// <param name="scm">The received SecurityControlMessage.</param> /// <param name="scm_reply">A prepared reply message (with headers and such.</param> /// <param name="return_path">Where to send the result.</param> /// <param name="low_level_sender">We expect the return_path to not be an edge or /// some other type of "low level" sender, so this contains the parsed out value.</param> protected void HandleControlCookie(SecurityAssociation sa, MemBlock calc_cookie, SecurityControlMessage scm, SecurityControlMessage scm_reply, ISender return_path, ISender low_level_sender) { ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Received Cookie from: " + low_level_sender); scm_reply.Type = SecurityControlMessage.MessageType.CookieResponse; scm_reply.RemoteCookie = scm.LocalCookie; scm_reply.LocalCookie = calc_cookie; if(SecurityPolicy.GetPolicy(scm.SPI).PreExchangedKeys) { scm_reply.CAs = new List<MemBlock>(0); } else { scm_reply.CAs = _ch.SupportedCAs; } ICopyable to_send = new CopyList(SecureControl, scm_reply.Packet); return_path.Send(to_send); ProtocolLog.WriteIf(ProtocolLog.Security, GetHashCode() + " Successful Cookie from: " + low_level_sender); }
/** * Abandon any attempts to get requests for the given ID. * @throw Exception if handler is not the original handler for this Request */ public void StopRequest(int request_id, IReplyHandler handler) { RequestState rs = null; lock( _sync ) { if( !_req_state_table.TryTake(request_id, out rs)) { rs = null; } } if( rs != null ) { /* * Send an ack for this reply: */ byte[] ack_payload = new byte[5]; ack_payload[0] = (byte)ReqrepType.ReplyAck; NumberSerializer.WriteInt(request_id, ack_payload, 1); ICopyable data = new CopyList(PType.Protocol.ReqRep, MemBlock.Reference(ack_payload)); foreach(ISender ret_path in rs.Repliers) { try { //Try to send an ack, but if we can't, oh well... ret_path.Send(data); } catch { } } } }
/** <summary>Creates a response from the parameter fields with RDATA being a memory chunk. This is for MDNS which supports caching</summary> <param name="NAME">The name resolved.</param> <param name="TYPE">The query type.</param> <param name="CLASS">The network type.</param> <param name="CACHE_FLUSH">Flush the dns cache in the client.</param> <param name="TTL">How long to hold the result in the local dns cache.</param> <param name="RDATA">RDATA in String format.</param> */ public Response(String NAME, DNSPacket.TYPES TYPE, DNSPacket.CLASSES CLASS, bool CACHE_FLUSH, int TTL, String RDATA) { this.NAME = NAME; this.CLASS = CLASS; this.TTL = TTL; this.TYPE = TYPE; this.CLASS = CLASS; this.CACHE_FLUSH = CACHE_FLUSH; this.RDATA = RDATA; if(TYPE == DNSPacket.TYPES.A) { NAME_BLOB = DNSPacket.HostnameStringToMemBlock(NAME); RDATA_BLOB = DNSPacket.IPStringToMemBlock(RDATA); } else if(TYPE == DNSPacket.TYPES.PTR) { if(DNSPacket.StringIsIP(NAME)) { NAME_BLOB = DNSPacket.PtrStringToMemBlock(NAME); } else { NAME_BLOB = DNSPacket.HostnameStringToMemBlock(NAME); } RDATA_BLOB = DNSPacket.HostnameStringToMemBlock(RDATA); } else { throw new Exception("Invalid Query TYPE: " + TYPE + "!"); } RDLENGTH = (short) RDATA_BLOB.Length; // 2 for TYPE + 2 for CLASS + 4 for TTL + 2 for RDLENGTH byte[] data = new byte[10]; int idx = 0; data[idx++] = (byte) ((((int) TYPE) >> 8) & 0xFF); data[idx++] = (byte) (((int) TYPE) & 0xFF); byte cache_flush = 0x80; if(!CACHE_FLUSH) { cache_flush = 0x00; } data[idx++] = (byte) (((((int) CLASS) >> 8) & 0x7F) | cache_flush); data[idx++] = (byte) (((int) CLASS) & 0xFF); data[idx++] = (byte) ((TTL >> 24) & 0xFF); data[idx++] = (byte) ((TTL >> 16) & 0xFF); data[idx++] = (byte) ((TTL >> 8) & 0xFF); data[idx++] = (byte) (TTL & 0xFF); data[idx++] = (byte) ((RDLENGTH >> 8) & 0xFF); data[idx] = (byte) (RDLENGTH & 0xFF); _icpacket = new CopyList(NAME_BLOB, MemBlock.Reference(data), RDATA_BLOB); }
static void Main(string[] args) { //log.Debug( "Starting the Brunet Echo Tester" ); String config_file = args[0]; NetworkConfiguration network_configuration = NetworkConfiguration.Deserialize(config_file); int port_selection = Convert.ToInt32(args[1]); //There will be 10 different ports available for use: 0, 1, 2.. //for example, node 0 on a machine will use port_selection # 0, node 1 on a machine will use port_selection # 1 ///There will be multiple BruNet nodes on the same machine. The following is a list of possible ports used int list_size = 150; int [] port_list = new int[list_size]; for(int i = 0; i < list_size; i++){ port_list[i] = 25000 + i; } ///The line below is used when there is only one node per machine //int local_host_index = network_configuration.GetLocalHostIndex(); int desired_port = port_list[port_selection]; int local_host_index = network_configuration.GetLocalHostIndex(desired_port); NodeConfiguration this_node_configuration = (NodeConfiguration)network_configuration.Nodes[local_host_index]; TransportAddressConfiguration local_ta_configuration = (TransportAddressConfiguration)this_node_configuration.TransportAddresses[0]; short port = local_ta_configuration.Port; SHA1 sha = new SHA1CryptoServiceProvider(); String local_ta = local_ta_configuration.GetTransportAddressURI(); //We take the local transport address plus the port number to be hashed to obtain a random AHAddress byte[] hashedbytes = sha.ComputeHash(Encoding.UTF8.GetBytes(local_ta + port)); //inforce type 0 hashedbytes[Address.MemSize - 1] &= 0xFE; AHAddress _local_ahaddress = new AHAddress(hashedbytes); Node this_node = new StructuredNode( _local_ahaddress ); ///Node this_node = new HybridNode( new AHAddress( new BigInteger( 2*(local_host_index+1) ) ) ); String file_string = "./data/brunetadd" + Convert.ToString(desired_port) + ".log"; StreamWriter sw = new StreamWriter(file_string, false); sw.WriteLine( "local_address " + this_node.Address.ToBigInteger().ToString() + " " + Dns.GetHostName() + ":" + port); sw.Close(); if ( local_ta_configuration.Protocol == "tcp" ) { this_node.AddEdgeListener( new TcpEdgeListener(port) ); } else if( local_ta_configuration.Protocol == "udp" ) { this_node.AddEdgeListener( new UdpEdgeListener(port) ); } int remote_node_index = local_host_index-1; int num_remote_ta = 20; //20 nodes on the list to try to bootstrap to if (local_host_index!=0) { NodeConfiguration remote_node_configuration = (NodeConfiguration)network_configuration.Nodes[0]; TransportAddressConfiguration remote_ta_configuration = (TransportAddressConfiguration)remote_node_configuration.TransportAddresses[0]; String remote_ta = remote_ta_configuration.GetTransportAddressURI(); this_node.RemoteTAs.Add( TransportAddressFactory.CreateInstance( remote_ta ) ); } while ( (remote_node_index>=0) && (num_remote_ta>=0) ) { NodeConfiguration remote_node_configuration = (NodeConfiguration)network_configuration.Nodes[remote_node_index]; TransportAddressConfiguration remote_ta_configuration = (TransportAddressConfiguration)remote_node_configuration.TransportAddresses[0]; String remote_ta = remote_ta_configuration.GetTransportAddressURI(); this_node.RemoteTAs.Add( TransportAddressFactory.CreateInstance( remote_ta ) ); System.Console.WriteLine("Adding {0}", remote_ta); remote_node_index--; num_remote_ta--; } /* NodeConfiguration remote_node_configuration = (NodeConfiguration)network_configuration.Nodes[remote_node_index]; TransportAddressConfiguration remote_ta_configuration = (TransportAddressConfiguration)remote_node_configuration.TransportAddresses[0]; String remote_ta = remote_ta_configuration.GetTransportAddressURI(); this_node.RemoteTAs.Add( TransportAddressFactory.CreateInstance( remote_ta ) );*/ EchoTester echo_printer = new EchoTester(); this_node.GetTypeSource(PType.Protocol.Echo).Subscribe(echo_printer, this_node); this_node.Connect(); //Send a "hello message" to a random neighbor ASCIIEncoding ascii = new ASCIIEncoding(); //Make the target addresses AHAddress target = new AHAddress( new BigInteger( 2*(remote_node_index+1) ) ); string hello_msg = "hello, brunet"; int byteCount = ascii.GetByteCount(hello_msg); byte[] bytes = new byte[byteCount + 1]; ascii.GetBytes(hello_msg, 0, hello_msg.Length, bytes, 1); // update the payload // This is a request, so the first byte is greater than zero bytes[0] = (byte) 1; ICopyable p = new CopyList(PType.Protocol.AH, new AHHeader(0, 30, this_node.Address, target, AHHeader.Options.Greedy), PType.Protocol.Echo, MemBlock.Reference(bytes)); ///RDP Experiment: sending the echo packet periodically /* int seq = 0; while(true){ int start_time = System.DateTime.Now.Millisecond; this_node.Send(p); Console.WriteLine("Seq = {0}, Start Time = {1}", seq, start_time); System.Threading.Thread.Sleep(10000); seq++; }*/ ///The following is a while-loop for the local node to Brunet-ping all other nodes in the network System.Threading.Thread.Sleep(60000); ///IMPORTANT: change this parameter so we wait longer for larger network Random uid_generator = new Random( DateTime.Now.Millisecond + local_ta.GetHashCode() + port); bytes = new byte[5]; int target_index = 0, num_pings = 10, wait_time = 10000; //the wait_time is in ms double ping_time; PingWrapper pw = new PingWrapper(); while( target_index < network_configuration.Nodes.Count ){ if(target_index != local_host_index){///we do not ping the local machine NodeConfiguration target_node_configuration = (NodeConfiguration)network_configuration.Nodes[target_index]; TransportAddressConfiguration target_ta_configuration = (TransportAddressConfiguration)target_node_configuration.TransportAddresses[0]; short target_port = target_ta_configuration.Port; double ping1 = pw.Ping(target_ta_configuration.Address, 10000); double ping2 = pw.Ping(target_ta_configuration.Address, 10000); if(ping1 >= 0 || ping2 >= 0){ //we gather the data only when the node is ping-able sha = new SHA1CryptoServiceProvider(); String target_ta = target_ta_configuration.GetTransportAddressURI(); //We take the transport address plus the port number to be hashed to obtain a random AHAddress hashedbytes = sha.ComputeHash(Encoding.UTF8.GetBytes(target_ta + target_port)); //inforce type 0 hashedbytes[Address.MemSize - 1] &= 0xFE; AHAddress _target_ahaddress = new AHAddress(hashedbytes); for(int i = 0; i < num_pings; i++){ //ping and Brunet-ping the target node for a number of times int uid = uid_generator.Next(); //this is the unique id of the packet // update the payload // This is a request, so the first byte is greater than zero bytes[0] = (byte) 1; NumberSerializer.WriteInt(uid, bytes, 1); p = new CopyList(PType.Protocol.AH, new AHHeader(0, 30, this_node.Address, _target_ahaddress, AHHeader.Options.Greedy), PType.Protocol.Echo, MemBlock.Reference(bytes)); this_node.Send(p); ping_time = pw.Ping(target_ta_configuration.Address, wait_time); //wait wait_time number of ms System.Console.WriteLine("Ping time: {0}",ping_time); System.Threading.Thread.Sleep(wait_time); }//end of for-loop } }//end of if-loop target_index++; }//end of while-loop }
/** <summary>Sends the data over the unicast socket.</summary> <param name="data">The data to send.</summary> */ public virtual void Send(ICopyable data) { // Silly users can trigger a handful of exceptions here... try { data = new CopyList(IPHandler.MagicCookie, data); byte[] buffer = new byte[data.Length]; int length = data.CopyTo(buffer, 0); _s.SendTo(buffer, 0, length, 0, EndPoint); } catch(System.Net.Sockets.SocketException sx) { throw new SendException(true, "SocketException", sx); } catch (ObjectDisposedException odx) { throw new SendException(false, "Socket appears to be disposed", odx); } catch (Exception e) { ProtocolLog.WriteIf(ProtocolLog.Exceptions, "ERROR: " + e); throw new SendException(true, "Socket appears to be disposed", e); } }
/** <summary>Sends the data over the multicast socket.</summary> <param name="data">The data to send.</summary> */ public override void Send(ICopyable data) { IPAddress[] ips = LocalIPAddresses; if(ips == null) { ips = IPHandler.GetLocalIPAddresses(); } // Silly users can trigger a handful of exceptions here... try { data = new CopyList(IPHandler.MagicCookie, data); byte[] buffer = new byte[data.Length]; int length = data.CopyTo(buffer, 0); // I REALLY HATE THIS but we can't be setting this option in more than one thread! lock(_s) { foreach(IPAddress ip in ips) { /* * This can throw an exception on an invalid address, we need to skip it and move on! * Never showed to be an issue in Linux, but Windows does some weird things. */ try { _s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, IPHandler.IPAddressToInt(ip)); } catch { continue; } _s.SendTo(buffer, 0, length, 0, EndPoint); } } } catch(System.Net.Sockets.SocketException sx) { throw new SendException(true, "SocketException", sx); } // Can't pass the fact that the IPHandler is not running :-/ catch (ObjectDisposedException odx) { throw new SendException(false, "Socket appears to be disposed", odx); } catch (Exception e) { ProtocolLog.WriteIf(ProtocolLog.Exceptions, "ERROR: " + e); throw new SendException(true, "Socket appears to be disposed", e); } }
protected override void UpdatePacket() { try { byte[] b = new byte[4 + 4 + 4]; int pos = 0; NumberSerializer.WriteInt(_spi, b, pos); pos += 4; NumberSerializer.WriteInt(_epoch, b, pos); pos += 4; NumberSerializer.WriteInt(_seqid, b, pos); MemBlock header = MemBlock.Reference(b); _icpacket = new CopyList(header, _encrypted_data); } catch(Exception e) { throw new Exception("Missing data to build packet!"); } base.UpdatePacket(); }
///<summary>All outgoing data filters through here.</summary> public void Send(ICopyable data) { if(!_active) { if(_closed == 1) { throw new SendException(false, "SA closed, unable to send!"); } UpdateSH(null, null); return; } // prepare the packet SecurityDataMessage sdm = new SecurityDataMessage(); sdm.SPI = _spi; sdm.Data = data as MemBlock; if(sdm.Data == null) { byte[] b = new byte[data.Length]; data.CopyTo(b, 0); sdm.Data = MemBlock.Reference(b); } // Encrypt it! SecurityHandler sh = _current_sh; try { sh.SignAndEncrypt(sdm); } catch { if(sh != _current_sh) { _current_sh.SignAndEncrypt(sdm); } else { throw; } } // Prepare for sending and send over the underlying ISender! data = new CopyList(SecurityOverlord.Security, SecurityOverlord.SecureData, sdm.ICPacket); try { _sender.Send(data); _running = true; } catch (Exception e) { Close("Failed on sending"); throw new SendException(false, "Failed on sending closing...", e); } }
/** * This is how you invoke a method on a remote host. * Results are put into the Channel. * * If you want to have an Event based approach, listen to the EnqueueEvent * on the Channel you pass for the results. That will be fired * immediately from the thread that gets the result. * * When a result comes back, we put and RpcResult into the Channel. * When you have enough responses, Close the queue (please). The code * will stop sending requests after the queue is closed. If you never close * the queue, this will be wasteful of resources. * * @param target the sender to use when making the RPC call * @param q the Channel into which the RpcResult objects will be placed. * q may be null if you don't care about the response. * @param method the Rpc method to call * * @throw Exception if we cannot send the request for some reason. */ virtual public void Invoke(ISender target, Channel q, string method, params object[] args) { //build state for the RPC call RpcRequestState rs = new RpcRequestState(); rs.Results = q; rs.RpcTarget = target; object[] rpc_call = new object[2]; rpc_call[0] = method; if( args != null ) { rpc_call[1] = args; } else { //There are no args, which we represent as a zero length list rpc_call[1] = new object[0]; } AdrCopyable req_copy = new AdrCopyable(rpc_call); #if RPC_DEBUG Console.Error.WriteLine("[RpcClient: {0}] Invoking method: {1} on target: {2}", _rrman.Info, method, target); #endif ICopyable rrpayload = new CopyList( PType.Protocol.Rpc, req_copy ); int reqid = _rrman.SendRequest(target, ReqrepManager.ReqrepType.Request, rrpayload, this, rs); //Make sure we stop this request when the queue is closed. if( q != null ) { try { q.CloseEvent += delegate(object qu, EventArgs eargs) { _rrman.StopRequest(reqid, this); }; } catch { if(q.Closed) { _rrman.StopRequest(reqid, this); } else { throw; } } } }
/// <summary>This begins the SecurityAssociation exchange protocol over the /// specified SecurityAssociation.</summary> protected void StartSA(SecurityAssociation sa) { SecurityControlMessage scm_reply = new SecurityControlMessage(); scm_reply.Version = Version; scm_reply.SPI = sa.SPI; scm_reply.Type = SecurityControlMessage.MessageType.Cookie; scm_reply.LocalCookie = CalculateCookie(sa.Sender); ICopyable to_send = new CopyList(Security, SecureControl, scm_reply.Packet); _rrman.SendRequest(sa.Sender, ReqrepManager.ReqrepType.Request, to_send, this, sa); }