public RPCResult <bool> PacketReceived(byte[] packet, int dev_no, int payload_offset, int payload_len, p_addr src) { /* Parse the provided packet */ byte type = packet[payload_offset]; byte code = packet[payload_offset + 1]; uint csum = ipv4.calc_checksum(packet, payload_offset, payload_len); if (csum != 0) { System.Diagnostics.Debugger.Log(0, null, "Received ICMP message with " + "invalid checksum " + csum.ToString("X4")); return(false); } ushort ident = net.ReadWord(packet, payload_offset + 4); ushort seq = net.ReadWord(packet, payload_offset + 6); System.Diagnostics.Debugger.Log(0, null, "ICMP message received from " + src.ToString() + ": type: " + type.ToString() + ", code: " + code.ToString() + ", ident: " + ident.ToString() + ", seq: " + seq.ToString()); return(true); }
public void TransmitEthernetPacket(byte[] packet, int dev_no, int payload_offset, int payload_len, p_addr dest, ushort etype) { /* Build an ethernet packet from the higher level packet passed to us. * * First, decide if we have enough space in the original buffer to * build the packet around. We need 14 bytes before the packet and * optionally 4 bytes after if the device doesn't add FCS. * * TODO: add support also for padding here */ var nd = devs[dev_no]; bool need_new_buf = false; int header_len = 14; if (payload_offset < header_len) { need_new_buf = true; } int crc_len = 0; if (nd.dev_appends_crc_on_tx == false) { crc_len = 4; } if (packet.Length < payload_offset + payload_len + crc_len) { need_new_buf = true; } if (need_new_buf) { byte[] new_buf = new byte[header_len + crc_len + payload_len]; for (int i = 0; i < payload_len; i++) { new_buf[header_len + i] = packet[payload_offset + i]; } payload_offset = header_len; packet = new_buf; } // Add in the header payload_offset -= header_len; payload_len += header_len; // dest var d = dest as HWAddr; if (d == null) { System.Diagnostics.Debugger.Log(0, null, "TransmitEthernetPacket: " + "dest is not a hardware address: " + dest.ToString()); return; } for (int i = 0; i < 6; i++) { packet[payload_offset + i] = d.MAC[i]; } // src for (int i = 0; i < 6; i++) { packet[payload_offset + 6 + i] = nd.HWAddr.MAC[i]; } // ethertype packet[payload_offset + 12] = (byte)((etype >> 8) & 0xff); packet[payload_offset + 13] = (byte)(etype & 0xff); // TODO: pad if required if (nd.dev_pads_on_tx == false && payload_len + crc_len < 64) { System.Diagnostics.Debugger.Log(0, null, "TransmitEthernetPacket: " + "packet too short and device does not automatically pad"); return; } // TODO: add FCS if required if (nd.dev_appends_crc_on_tx == false) { System.Diagnostics.Debugger.Log(0, null, "TransmitEthernetPacket: " + "device does not automatically add FCS"); return; } // Send packet nd.s.TransmitPacket(packet, dev_no, payload_offset, payload_len, dest); }
public RPCResult <HWAddr> ResolveAddress(int dev_no, p_addr addr) { /* Get the appropriate dictionary */ var prot_dict = GetProtocolDictionary(dev_no, addr.EtherType); /* If the cache contains the value we need, then we can use it * directly, otherwise we need to send a request for it */ HWAddr ret; if (prot_dict.TryGetValue(addr, out ret) == true) { System.Diagnostics.Debugger.Log(0, null, "Resolving " + addr.ToString() + " from cache to " + ret.ToString()); return(ret); } /* We need to send a ARP request out to the network, then respond to * the reply. Unfortunately, messages sent to the arp subsystem are * processed sequentially, therefore the reply will never be processed * until the current function exits. To get around this, we tell the * Invoke mechanism not to return from the synchronous call until * we have that response */ var e = CurrentMessage; e.EventSetsOnReturn = false; /* Send the request */ switch (addr.EtherType) { case 0x0800: /* IPv4 */ HWAddr sha = net.devs[dev_no].HWAddr; IPv4Address spa = net.devs[dev_no].addresses[0x0800] as IPv4Address; IPv4Address tpa = addr as IPv4Address; byte[] pkt = new byte[100]; int packet_offset = 32; int packet_len = 0; pkt[packet_offset + packet_len++] = 0x00; // HTYPE pkt[packet_offset + packet_len++] = 0x01; pkt[packet_offset + packet_len++] = 0x08; // PTYPE pkt[packet_offset + packet_len++] = 0x00; pkt[packet_offset + packet_len++] = 0x06; // HLEN pkt[packet_offset + packet_len++] = 0x04; // PLEN pkt[packet_offset + packet_len++] = 0x00; // OPER pkt[packet_offset + packet_len++] = 0x01; // SHA for (int i = 0; i < 6; i++) { pkt[packet_offset + packet_len++] = sha.MAC[i]; } // SPA for (int i = 0; i < 4; i++) { pkt[packet_offset + packet_len++] = spa.Octets[i]; } // THA for (int i = 0; i < 6; i++) { pkt[packet_offset + packet_len++] = 0; } // TPA for (int i = 0; i < 4; i++) { pkt[packet_offset + packet_len++] = tpa.Octets[i]; } net.TransmitEthernetPacket(pkt, dev_no, packet_offset, packet_len, HWAddr.Multicast, 0x0806); break; } // Store this request GetPendingRequestList(dev_no, addr.EtherType, addr).Add(e); // Return null for now until we actually get a result return(null); }