/// <summary>Look up a hostname given a Dns request in the form of IPPacket /// </summary> /// <param name="in_ip">An IPPacket containing the Dns request</param> /// <returns>An IPPacket containing the results</returns> public virtual IPPacket LookUp(IPPacket in_ip) { UdpPacket in_udp = new UdpPacket(in_ip.Payload); DnsPacket in_dns = new DnsPacket(in_udp.Payload); ICopyable out_dns = null; string qname = string.Empty; bool invalid_qtype = false; try { string qname_response = String.Empty; qname = in_dns.Questions[0].QName; DnsPacket.Types type = in_dns.Questions[0].QType; if(type == DnsPacket.Types.A || type == DnsPacket.Types.AAAA) { qname_response = AddressLookUp(qname); } else if(type == DnsPacket.Types.Ptr) { qname_response = NameLookUp(qname); } else { invalid_qtype = true; } if(qname_response == null) { throw new Exception("Unable to resolve"); } Response response = new Response(qname, in_dns.Questions[0].QType, in_dns.Questions[0].QClass, 1800, qname_response); //Host resolver will not accept if recursive is not available //when it is desired DnsPacket res_packet = new DnsPacket(in_dns.ID, false, in_dns.Opcode, true, in_dns.RD, in_dns.RD, in_dns.Questions, new Response[] {response}, null, null); out_dns = res_packet.ICPacket; } catch(Exception e) { bool failed_resolve = false; // The above resolver failed, let's see if another resolver works if(_forward_queries) { try { out_dns = Resolve(_name_server, (byte[]) in_dns.Packet); } catch(Exception ex) { e = ex; failed_resolve = true; } } if(!_forward_queries || failed_resolve) { ProtocolLog.WriteIf(IpopLog.Dns, "Failed to resolve: " + qname + "\n\t" + e.Message); out_dns = DnsPacket.BuildFailedReplyPacket(in_dns, !invalid_qtype); } } UdpPacket out_udp = new UdpPacket(in_udp.DestinationPort, in_udp.SourcePort, out_dns); return new IPPacket(IPPacket.Protocols.Udp, in_ip.DestinationIP, in_ip.SourceIP, out_udp.ICPacket); }
/// <summary>This method handles IPPackets that come from the TAP Device, i.e., /// local system.</summary> /// <remarks>Currently this supports HandleMulticast (ip[0] >= 244 && /// ip[0]<=239), HandleDns (dport = 53 and ip[3] == 1), dhcp (sport 68 and /// dport 67.</remarks> /// <param name="packet">The packet from the TAP device</param> /// <param name="from"> This should always be the tap device</param> protected virtual void HandleIPOut(EthernetPacket packet, ISender ret) { IPPacket ipp = new IPPacket(packet.Payload); if(IpopLog.PacketLog.Enabled) { ProtocolLog.Write(IpopLog.PacketLog, String.Format( "Outgoing {0} packet::IP src: {1}, IP dst: {2}", ipp.Protocol, ipp.SSourceIP, ipp.SDestinationIP)); } if(!IsLocalIP(ipp.SourceIP)) { // This really ought to have been caught in ARP, but just in case... HandleNewStaticIP(packet.SourceAddress, ipp.SourceIP); return; } UdpPacket udpp = null; switch(ipp.Protocol) { case IPPacket.Protocols.Udp: udpp = new UdpPacket(ipp.Payload); if(udpp.SourcePort == _dhcp_client_port && udpp.DestinationPort == _dhcp_server_port) { if(HandleDhcp(ipp)) { return; } } else if(udpp.DestinationPort == 53 && ipp.DestinationIP.Equals(_dhcp_server.ServerIP)) { if(HandleDns(ipp)) { return; } } break; } if(ipp.DestinationIP[0] >= 224 && ipp.DestinationIP[0] <= 239) { // We don't want to send Brunet multicast packets over IPOP! if(udpp != null && udpp.DestinationPort == IPHandler.mc_port) { return; } else if(HandleMulticast(ipp)) { return; } } if(ipp.DestinationIP.Equals(IPPacket.BroadcastAddress)) { if(HandleBroadcast(ipp)) { return; } } if(_dhcp_server == null || ipp.DestinationIP.Equals(_dhcp_server.ServerIP)) { return; } Address target = null; try { target = _address_resolver.Resolve(ipp.DestinationIP) as AHAddress; } catch(AddressResolutionException ex) { if(ex.Issue != AddressResolutionException.Issues.DoesNotExist) { throw; } // Otherwise nothing to do, mapping doesn't exist... } if(target != null) { SendIP(target, packet.Payload); } }
/// <summary>This is used to process a dhcp packet on the node side, that /// includes placing data such as the local Brunet Address, Ipop Namespace, /// and other optional parameters in our request to the dhcp server. When /// receiving the results, if it is successful, the results are written to /// the TAP device.</summary> /// <param name="ipp"> The IPPacket that contains the Dhcp Request</param> /// <param name="dhcp_params"> an object containing any extra parameters for /// the dhcp server</param> /// <returns> true on if dhcp is supported.</returns> protected virtual bool HandleDhcp(IPPacket ipp) { UdpPacket udpp = new UdpPacket(ipp.Payload); DhcpPacket dhcp_packet = new DhcpPacket(udpp.Payload); MemBlock ether_addr = dhcp_packet.chaddr; if(_dhcp_config == null) { return true; } DhcpServer dhcp_server = CheckOutDhcpServer(ether_addr); if(dhcp_server == null) { return true; } MemBlock last_ip = null; _ether_to_ip.TryGetValue(ether_addr, out last_ip); byte[] last_ipb = (last_ip == null) ? null : (byte[]) last_ip; WaitCallback wcb = delegate(object o) { ProtocolLog.WriteIf(IpopLog.DhcpLog, String.Format( "Attempting Dhcp for: {0}", Utils.MemBlockToString(ether_addr, '.'))); DhcpPacket rpacket = null; try { rpacket = dhcp_server.ProcessPacket(dhcp_packet, AppNode.Node.Address.ToString(), last_ipb); } catch(Exception e) { ProtocolLog.WriteIf(IpopLog.DhcpLog, e.Message); CheckInDhcpServer(dhcp_server); return; } /* Check our allocation to see if we're getting a new address */ MemBlock new_addr = rpacket.yiaddr; UpdateMapping(ether_addr, new_addr); MemBlock destination_ip = ipp.SourceIP; if(destination_ip.Equals(IPPacket.ZeroAddress)) { destination_ip = IPPacket.BroadcastAddress; } UdpPacket res_udpp = new UdpPacket(_dhcp_server_port, _dhcp_client_port, rpacket.Packet); IPPacket res_ipp = new IPPacket(IPPacket.Protocols.Udp, rpacket.siaddr, destination_ip, res_udpp.ICPacket); EthernetPacket res_ep = new EthernetPacket(ether_addr, EthernetPacket.UnicastAddress, EthernetPacket.Types.IP, res_ipp.ICPacket); Ethernet.Send(res_ep.ICPacket); CheckInDhcpServer(dhcp_server); }; ThreadPool.QueueUserWorkItem(wcb); return true; }
/** <summary>Implements the ITranslator portion for ManagedAddress..., takes an IP Packet, based upon who the originating Brunet Sender was, changes who the packet was sent from and then switches the destination address to the local nodes address. Takes incomming packets only.</summary> <param name="packet">The IP Packet to translate.</param> <param name="from">The Brunet address the packet was sent from.</param> <returns>The translated IP Packet.</returns> */ public MemBlock Translate(MemBlock packet, Address from) { UpdateCounter(_rx_counters, from); MemBlock source_ip = _addr_ip[from]; if(source_ip == null) { throw new Exception("Invalid mapping " + from + "."); } // Attempt to translate a packet IPPacket ipp = new IPPacket(packet); // hdr is everything in the packet up to the source IP, dest IP, "options" // and data MemBlock hdr = packet.Slice(0,12); // Pull the "fragment" info from the header. If it is not fragmented, we // can deal with the packet. DNS packets should never be sent as fragments bool fragment = ((hdr[6] & 0x1F) | hdr[7]) != 0; //should there be a field in the IPPacket class for this? MemBlock dest_ip = ipp.DestinationIP; byte dest_ip_first_byte = dest_ip[0]; bool is_multicast = dest_ip_first_byte > 223 && dest_ip_first_byte < 240; //multicast addresses are 224.0.0.0 through 239.255.255.255 if(ipp.Protocol == IPPacket.Protocols.Udp && !fragment) { //simple UDP UdpPacket udpp = new UdpPacket(ipp.Payload); foreach(IProtocolTranslator<UdpPacket> i in _udp_translators) { if(i.MatchesProtocol(udpp)) { udpp = i.Translate(udpp, source_ip, ipp.SourceIP, ipp.DestinationIP); return new IPPacket(ipp.Protocol, source_ip, is_multicast? ipp.DestinationIP: _local_ip, hdr, udpp.ICPacket).Packet; } } } //fallback return IPPacket.Translate(packet, source_ip, is_multicast? ipp.DestinationIP: _local_ip ); }