I am building a Wake On Lan program in C# i have found lots of code for WOL but whatever i have found thus far does not work. i believe this is because i cannot enable IP directed broadcast (The customer's security policy will not enable this in order to prevent DOS attacks).
i am looking for a way to send the magic packet over ethernet directly to the requested mac address - right now it seems to be sending over UDP to 255.255.255.255
(What i am don't understand is why it needs to send to 255.255.255.255 and not to the mac itself)
here is the code i have as of now (can't remember where i found it).
public static bool WakeOnLan(string MacAddress)
{
try
{
MacAddress = MacAddress.Replace("-", "");
MacAddress = MacAddress.Replace(":", "");
if (MacAddress.Length != 12)
{
return false;
}
byte[] mac = new byte[6];
for (int k = 0; k < 6; k++)
{
mac[k] = Byte.Parse(MacAddress.Substring(k * 2, 2), System.Globalization.NumberStyles.HexNumber);
}
// WOL packet is sent over UDP 255.255.255.0:40000.
System.Net.Sockets.UdpClient client = new System.Net.Sockets.UdpClient();
client.Connect(System.Net.IPAddress.Broadcast, 4000);
byte[] packet = new byte[17 * 6];
for (int i = 0; i < 6; i++)
packet[i] = 0xFF;
for (int i = 1; i <= 16; i++)
for (int j = 0; j < 6; j++)
packet[i * 6 + j] = mac[j];
client.Send(packet, packet.Length);
return true;
}
catch
{
return false;
}
}
Any help would be greatly appreciated.
thanx
WoL frames are sent to the broadcast MAC address, ffff:ffff:ffff. To do that, you must send the IP packet to either the network or limited broadcast address. Broadcasts do not cross routers because this is a huge security hole.
Implementation that must send WoL from different network do this by placing a WoL server on the LAN, and send commands to the WoL server that will then send WoL frames on the LAN.
Edit:
If you are trying to do WoL with the source and destination on the same LAN, you can use either the LAN or limited broadcast because the frames will not try to cross a router.
You really should not use UDP. This can be accomplished with an ethernet frame. Just send the frame to ffff:ffff:ffff. IP addresses are only needed to get a packet from one network to another network. Data on a LAN is delivered in layer-2, e.g. ethernet, frames.
You can just use an EtherType of 0x0842, then in the frame payload, put in 0xffffffffffff followed immediately by 16 repetitions of the target MAC address. That is all that is necessary for a "Magic Packet" because it is really a frame, not a packet.
Related
So in my client I am looking for a way to return how many times a background worker was run to a server. Here is the code section for the client:
}
public int searchcount = 1;
public void SL_Click(object sender, EventArgs e)
{
try
{
TcpClient tcpclnt = new TcpClient();
tcpclnt.Connect(RecieveIP.Text, 8001); // use the ipaddress as in the server program
MessageBox.Show("Connected");
Stream stm = tcpclnt.GetStream();
MessageBox.Show("Listening for information......");
byte[] bb = new byte[100];
int k = stm.Read(bb, 0, 100);
string atk = Encoding.UTF8.GetString(bb.AsSpan(0, k));
Console.WriteLine($"S Connected to attack server at IPv4 address {RecieveIP.Text} Attack command Received: {atk}. If command is g, attacking google. Y means attacking yahoo. A means attacking aol. Yo meants attacking youtube, and s is attacking spotify");//test
//if you want your check
//this will not work if your incoming data contains white space or other bytes that were converted.
if (atk == "g" || atk.Contains("g"))
MessageBox.Show("Recieved Command " + atk);
if (atk == "g")
{
MessageBox.Show("Google");
search.RunWorkerAsync();
On thought, I do have a string
public int searchcount = 1;
Which the background worker in question adds one to display to the person running the client how many times it was run.
Console.WriteLine("Since start: " + count++.ToString());
Is there a way to return the count++ string to the server via both TCP and UDP? Thanks.
TCP(socket) is a protocol that you can send packages both ways. Udp on the other hand is stateless, you can only send packages from client to server. You cant maintain UDP connections open and keep sending/receiving packages. That said, you can send packages from client to server using UDP if the server dont need to respond your package.
I'm really doing some resume on what tcp/udp protocols are and i really encourage you to read about them on MS official docs before using anything on production.
Here some TCP , UDP and sockets examples and documentation on MS official docs.
Tcp Client/Server
Udp Client/Server
Sockets
I'm trying to communicate with a modbus device in my network at ip 192.168.1.76. My host computer address is 192.168.1.132. I'm not able to connect to or listen to device ip.
basically i'm using NModbus4 library. I've created a ModbusTCPSlave and attached the tcp listener to it. then i assigned ModbusSlaveRequestReceived event to that slave. but it gives nothing in return when i try to change register values directly from Modscan software.
Main()
{
var masterEndpoint = new IPEndPoint(IPAddress.Parse("192.168.1.132"), 502);
var listener = new TcpListener(IPAddress.Any, 502);
listener.Start();
var slave = ModbusTcpSlave.CreateTcp(255, new TcpListener(masterEndpoint), 10);
slave.ModbusSlaveRequestReceived += Modbus_Request_Event;
slave.Listen();
}
private static void Modbus_Request_Event(object sender, Modbus.Device.ModbusSlaveRequestEventArgs e)
{
//disassemble packet from master
byte fc = e.Message.FunctionCode;
byte[] data = e.Message.MessageFrame;
byte[] byteStartAddress = new byte[] { data[3], data[2] };
byte[] byteNum = new byte[] { data[5], data[4] };
Int16 StartAddress = BitConverter.ToInt16(byteStartAddress, 0);
Int16 NumOfPoint = BitConverter.ToInt16(byteNum, 0);
Console.WriteLine(fc.ToString() + "," + StartAddress.ToString() + "," + NumOfPoint.ToString());
}
I expect to get function code, start address and number of points in console application when any register value is changed
I copied your code. Changed the IP address to my "server" and it worked.
So, the issue you are having is either in the setup of your "server" or in the PLC program.
I thought that I had to do some port forwarding on my router. I did not. It did not make a difference.
Server setup:
Your "server"'s IP address needs to be static. Whether your 'server' is your development system or not. And don't forget when you deploy... Server's IP address has to be static as well (not that it wouldn't be...just saying)
Add an inbound Firewall rule to allow connections to the port, in this case 502, otherwise you'll have to allow access every time you launch/start a test.
PLC program
I am using Click PLC's by Koyo. Not sure if this is the rule for all PLC's or not; but, we had to add a line of code to "write" the values we wanted to pick up off the TCP stream. Without the write, the PLC was not sending out a request to join the TcpListener.
Last:
The code to start your listener only needs to be this:
var listener = new TcpListener(IPAddress.Parse("192.168.1.244"), 502);
listener.Start();
var slave = ModbusTcpSlave.CreateTcp(255, listener, 10);
slave.ModbusSlaveRequestReceived += Modbus_Request_Event;
slave.Listen();
I'm trying to implement IP fragmentation using Pcap.Net.
It is simple for packets that are already built as the L3 payload is just split into parts.
I have a code that does it. It returns the list of packet fragments for sending it into the wire.
private static List<Packet> FragmentPacket(Packet packet)
{
EthernetLayer ethernetLayer = (EthernetLayer)packet.Ethernet.ExtractLayer();
IpV4Layer ipV4Layer = (IpV4Layer)packet.Ethernet.IpV4.ExtractLayer();
PayloadLayer payload = (PayloadLayer)packet.Ethernet.IpV4.Payload.ExtractLayer();
// implement IP fragmentation
int totalLength = payload.Length;
int fragmentLength = 1480;
int fragmentOffset = 0;
IpV4FragmentationOptions FragOptions;
List<Packet> fragmentsList = new List<Packet>();
while (fragmentOffset < totalLength)
{
if (fragmentOffset + fragmentLength >= totalLength)
{
//last fragment
FragOptions = IpV4FragmentationOptions.None;
fragmentLength = totalLength - fragmentOffset;
}
else
{
//more fragments to go
FragOptions = IpV4FragmentationOptions.MoreFragments;
}
IpV4Layer newipV4Layer =
new IpV4Layer
{
Source = ipV4Layer.Source,
CurrentDestination = ipV4Layer.CurrentDestination,
Fragmentation = new IpV4Fragmentation(FragOptions, (ushort)fragmentOffset),
HeaderChecksum = null, // Will be filled automatically.
Identification = 123,
Options = IpV4Options.None,
Protocol = ipV4Layer.Protocol,
Ttl = ipV4Layer.Ttl, // 128,
TypeOfService = ipV4Layer.TypeOfService,
};
byte[] newBuffer = payload.Data.ToArray();
PayloadLayer fragmentedPayload = new PayloadLayer { Data = new Datagram(newBuffer, fragmentOffset, fragmentLength) };
PacketBuilder builder = new PacketBuilder(ethernetLayer, ipV4Layer, fragmentedPayload);
fragmentsList.Add(builder.Build(DateTime.Now));
fragmentOffset = fragmentOffset + fragmentedPayload.Length;
}
return fragmentsList;
}
But what I'm actually doing is:
1) receiving large packet via Loopback interface (it is usually bigger than physical interface's MTU)
2) disassembling it, modifying IP addresses
3) building a new packet and sending it via Ethernet interface
Unfortunately, if the IP payload is bigger than MTU, exception happens as the packet needs to be fragmented before sending.
Because I'm changing IP address, then for TCP/UDP packets, the L4 checksum must be recalculated and this recalculation must take into account L3 header. Therefore it is needed to build L3+L4+payload part (to have L4 checksum properly calculated) and then split L4+payload into parts to fit L3 MTU.
I came into a solution in which I'm building a new packet (which is bigger than MTU) and then push it via above function to tear it into parts, and then I'm sending it using:
foreach (Packet newpacket in packetList)
communicator.SendPacket(newpacket);
This, however, requires to build the same packet twice and I'm trying to find a way in Pcap.Net to partially build a packet (including recalculation of L4 checksum) and at the same time divide it into fragments to fit MTU.
I don't know how to (and if this is possible in Pcap.Net) prepare L3 payload that would consist of tcpLayer/udpLayer + L4 payload since TCP checksum is calculated during building and then finally build the rest of packet.
If that was possible, I would just need to build the packet once splitting it into parts at the same time.
I'm working with a WiFi module written in C that connects to a TCP server written in C++/WinAPI. At the moment, I'm trying to write up some documentation on the protocol being used, as none currently exists. In order to make this a bit easier, I've written a simple application in C#/WinForms in order to more easily send and read received packets.
When working with the existing server, the module connects and then sends a packet with a serial number (i.e. #12345) as a byte array. A green LED also begins blinking when connected to the socket.
When using my new testing server, the server detects that the client is connected (socket.Connected == true), then StreamReader.ReadLine() begins receiving endless nulls. The LED on the client also does not blink green, so it looks as though the client is not connected to the socket.
I don't have a ton of experience with TCP/IP, can anyone see any flaws with the route I'm taking or think of any possible reason why the client end isn't detecting the connection/ sending it's serial number, while the server seems to be working just fine? Thanks in advance for any input.
EDIT:
Here is some of the state machine the module uses to connect to the server..
switch(TransmitState)
{
case CHECK_POLLTIME:
if(PollCounter >= Device.MinutesPerPoll)
{
PollCounter = 0;
TransmitState++; // initiate server communications
}
break;
case LOAD_SOCKET:
if(AppConfig.IsLinked != LINKED) break;
// Connect a socket to the remote TCP server
if(!TCPIsConnected(socket))
socket= TCPOpen(server_ip, server_port);
TransmitState++;
Timer = TickGet();
break;
case POLL_SERVER:
// Wait for the remote server to accept our connection request
if(!TCPIsConnected(socket))
{
// Time out if too much time is spent in this state
if(TickGet()-Timer > 5*TICK_SECOND)
{
// Close the socket so it can be used by other modules
TransmitState = SM_DISCONNECT;
}
break;
}
Timer = TickGet();
if(Bootloader)
break;
// Make certain the socket can be written to
if(U2Tx.count != 0) break;
// Place the application protocol data into the transmit buffer.
//packet needs to include UART commands to get through
TCPBuffer[0] = 0x1B; //ESC
TCPBuffer[1] = 'Z';
TCPBuffer[2] = AppConfig.ConnectionID;
TCPBuffer[3] = '0';
TCPBuffer[4] = '0';
TCPBuffer[5] = '0';
TCPBuffer[6] = '6';
TCPBuffer[7] = '#'; // represents serial number
TCPBuffer[8] = Device.Serial[0];
TCPBuffer[9] = Device.Serial[1];
TCPBuffer[10] = Device.Serial[2];
TCPBuffer[11] = Device.Serial[3];
TCPBuffer[12] = Device.Serial[4];
WF_TxBlock(TCPBuffer, 13);
TransmitState++;
break;
case PROCESS_RESPONSE:
...
I read the tutorials and so, but I am not getting it. It does let you send packets, but how can you tell Winpcap where to send those packets? Is there any header I should put on the packets so it will know to which ip/port's to forward it? I mean. Let's imagine I want to send some data to my MSN, as if I had wrote something to someone on my list. I can use the sendpacket(), but it will only take the packet/byte array as argument, not specifing to which app/ip/port so send it.
Thanks
You don't tell Winpcap where to send packets. You tell it to put a packet on the wire. The network switch will send the packet to the right destination. The TCP stack on the receiving end will send the packet to the right application/service. Obviously this means the routing information has to be in the packet itself.
To take your example, you'd need to put the IP address and TCP port of the appropriate MSN server in the packet. If you don't, your networking hardware will discard or misroute that packet.
This is how i sent an ARP request over the wire.
1. Define structures for the protocols i.e if you want to send ARP packets you will need a structure that will contain the data link layer(Ethernet header) and network layer (ARP Header). Correspondingly if you want to send a tcp packet over IP you will need a data structure for the ethernet header, ip header and tcp header.
once you defined the structures, initialize an instance of the structure with values you want i.e. if you want the packet to go to all machines in the network set the destination mac value of the Ethernet header to ff:ff:ff:ff:ff:ff if you want to send the packet to machine X with(IP address 192.168.0.88) then set the destination address in the ip layer to that value.
Once done you will need to declare a char* array and copy all the structures to the char* array to create a byte sequence and send it over the wire.
//Just to show you what i mean by defining structures doesn't //relate to the rest of the code snippet
typedef struct IP_header
{
u_char VersionNInternetHeaderLength; // Version (4 bits) + Internet header length (4 bits)
/*u_char version:4;
u_char HeaderLength:4;*/
u_char Type; // Type of service
u_short TotalLength; // Total length
u_short Identification; // Identification
u_char rsv : 1;
u_char df : 1;
u_char mf : 1;
u_char FragmentOffset1 : 5;
u_char FragmentOffset2;
//u_short Flags_fo; // Flags (3 bits) + Fragment offset (13 bits)
u_char TimeToLive; // Time to live
u_char Protocol; // Next level Protocol of the encapsulated payload
u_short Checksum; // Header checksum
IP_address SourceAddress; // Source address
IP_address DestinationAddress; // Destination address
u_int OptionNPadding; // Option + Padding
IP_header()
{
mf = 0;
rsv = 0;
df = 0;
FragmentOffset1 = 0;
FragmentOffset2 = 0;
TimeToLive = 128;
TotalLength = sizeof(IP_header);
Identification = 0xABCD;
Checksum = 0xABCD;
OptionNPadding = 0;
}
}IP_header;
Ethernet_header EthernetHeader;// = (Ethernet_header*)malloc(sizeof(Ethernet_header));
ARP_header ARPHeader ;//= (ARP_header*)malloc(sizeof(ARP_header));
ARPHeader.HardwareType = htons(1);
ARPHeader.ProtocolType = htons(0x800);
ARPHeader.OPCODE = htons(1);
ARPHeader.HeaderLength = 6;
ARPHeader.ProtocolLength = 4;
ARPHeader.SenderMAC = MY_FAKE_MAC;
ARPHeader.SenderIP = MY_IP;
ARPHeader.TargetMAC = MAC_address();
ARPHeader.TargetIP = Whose;
EthernetHeader.DestinationMAC = BROADCASTMAC;
EthernetHeader.SourceMAC = MY_FAKE_MAC;
EthernetHeader.EtherType = htons(0x806);
u_char* packet = (u_char*)malloc(sizeof(EthernetHeader) + sizeof(ARPHeader));
memcpy(packet, &EthernetHeader, sizeof(EthernetHeader));
memcpy(packet + sizeof(EthernetHeader), &ARPHeader, sizeof(ARPHeader));
SendPacket(packet);