Modbus TCP - Arduino - c

I have to implement a Modbus TCP using a TI Launchpad board which is similar to Arduino. I have the following snippet.
MbmByteArray[0] = 0x00;
MbmByteArray[1] = 0x01;
MbmByteArray[2] = 0x00;
MbmByteArray[3] = 0x00;
MbmByteArray[4] = 0x00;
MbmByteArray[5] = 0x0B;
MbmByteArray[6] = 0x01;
MbmByteArray[7] = 0x10;
MbmByteArray[8] = 0x00;
MbmByteArray[9] = 0x00;
MbmByteArray[10] = 0x00;
MbmByteArray[11] = 0x02;
MbmByteArray[12] = 0x04;
MbmByteArray[13] = 0x00;
MbmByteArray[14] = 0x08;
MbmByteArray[15] = 0x00;
MbmByteArray[16] = 0x00;
Serial.println("Written:");
for(int i=0;i<MbmByteArray[5]+6;i++) {
int a=0;
a = MbmClient.write(MbmByteArray[i]);
if(a)
{
// if something is written to the client I check what it is !
Serial.println(MbmByteArray[i]);
}
}
This is my client
You can see that the bytes are not received continuously. But my entire array is like a command to the client. Is there anyway to get it this way :
2016-06-17 14:28:00.252: Session created
2016-06-17 14:28:00.254: Session opened
2016-06-17 14:28:00.256: 17 bytes received
00 01 00 00 00 0B 01 10 00 00 00 02 04 00 07 00 00
2016-06-17 14:28:00.269: 12 bytes sent
< 00 01 00 00 00 06 01 10 00 00 00 02
Please help!

In general, when doing communication on any given line, file or media, you risk breaking up the data. Ethernet actually has a package size (MTU) that can/will be delivered unbroken. But that's another story. It'll be better if you deal with the issue, no matter protocol, hardware or platform. (Or at least be aware of it.)
When you read your ModbusTCP, you should make something like the following pseudo:
//read all ModbusTCP header
while less than 6 bytes received and not timed out and not error
read bytes
//read data
data_length = modbustcp_header position 5 and 6
while less than data_length and not timed out and not error
read bytes
The above function will collect the whole package, before "releasing" it to your engine. The algorithm will work for both sides of your setup. (Both the Texas hw and the PC.)
You could also (most likely) fiddle with the TI TCP stack and make it return bigger blocks. And I guess this was what you were asking for. But again, I wouldn't recommend going down that road.

Thank you Illishar !
I found a way to do it. In Arduino there is a client function, that could send the entire array without sending one value at a time.
byte command[17] = {0x00,0x01,0x00,0x00,0x00,0x0B,0x01,0x10,0x00,0x00,0x00,0x02,0x04,0x00,0x07,0x00,0x00};
MbmClient.write(command,17);
This client.write(buffer,number of elements) helps me to send the entire content in a single packet. It works like a charm :)

Related

Netfilter Kernel module doesn't get the ftp packets' data

Netfilter Kernel module doesn't get the FTP packets' data
Question
I've been trying to write a kernel module to read outgoing FTP packets' username, password and cmd by netfilter.When I test my code ,I find the ftp packets' length is right,but all the data I get is 0x00 when check kernel module's output.
Code
Here is my code. And I wirte a pkt_hex_dump functioin to dump all my packets's bytes above the Internet layer(Include Internet layer) accroding to this Printing sk_buff data:
/* Sample code to install a Netfilter hook function */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/icmp.h>
#include <linux/netdevice.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
MODULE_LICENSE("MIT");
MODULE_AUTHOR("1933");
MODULE_DESCRIPTION("An net sniff module for demonstration");
MODULE_VERSION("1.0");
/* Used to describe our Netfilter hooks */
static struct nf_hook_ops post_hook;
/* THESE values are used to keep the USERname and PASSword until
* they are queried. Only one USER/PASS pair will be held at one
* time
*/
static char *username = NULL;
static char *password = NULL;
static unsigned short src_port = 0;
static int have_pair = 0; /* Marks if we already have a pair */
/* dump packet's data */
void pkt_hex_dump(struct sk_buff *skb){
size_t len;
int rowsize = 16;
int i, l, linelen, remaining;
int li = 0;
uint8_t *data, ch;
struct iphdr *ip = (struct iphdr *)skb_network_header(skb);
printk("Packet hex dump:\n");
data = (uint8_t *) skb_network_header(skb);
len=ntohs(ip->tot_len);
remaining = len;
for (i = 0; i < len; i += rowsize) {
printk("%06d\t", li);
linelen = min(remaining, rowsize);
remaining -= rowsize;
for (l = 0; l < linelen; l++) {
ch = data[l];
printk(KERN_CONT "%02X ", (uint32_t) ch);
}
data += linelen;
li += 10;
printk(KERN_CONT "\n");
}
}
/* This is the hook function itself */
unsigned int watch_out(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
struct iphdr *ip = NULL;
struct tcphdr *tcp = NULL;
unsigned char *data=NULL;
ip = (struct iphdr *)skb_network_header(skb);
if (ip->protocol != IPPROTO_TCP){
return NF_ACCEPT;
}
tcp = (struct tcphdr *)skb_transport_header(skb);
/* Now check to see if it's an FTP packet */
if (tcp->dest!= htons(21)){
return NF_ACCEPT;
}
pkt_hex_dump(skb);
/* Parse the FTP packet for relevant information if we don't already
* have a username and password pair. */
data = (unsigned char *)((unsigned char *)tcp + (tcp->doff * 4));
printk("hex : data[0-3] = 0x%02x%02x%02x%02x\n", data[0], data[1], data[2], data[3]);
printk("char: data[0-3] = %c%c%c%c\n", data[0], data[1], data[2], data[3]);
printk("--------------- findpkt_iwant ------------------\n");
return NF_ACCEPT;
}
/* Initialisation routine */
int init_module(){
/* Fill in our hook structure */
post_hook.hook = watch_out; /* Handler function */
post_hook.hooknum = NF_INET_POST_ROUTING;
post_hook.pf = AF_INET;
post_hook.priority = NF_IP_PRI_FIRST; /* Make our function first */
nf_register_net_hook(&init_net,&post_hook);
// Debug
printk("HELLO: this is hello module speaking\n");
return 0;
}
/* Cleanup routine */
void cleanup_module(){
printk("HELLO : Goodbye!\n");
nf_unregister_net_hook(&init_net,&post_hook);
}
Enviroment
Linux 5.13.0-37-generic x86_64 GNU/Linux
Ubuntu 20.04.4 LTS
Makefile:
obj-m+=NetKernal.o
all:
make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules
The Kernel module's Output and the Wireshark' capture:
This is the whole demsg output when I connected to ftp server and inputed my username and password on my Local area network.
And this is the whole wireshark packet after adding filter rule: tcp.dstport == 21.The Internet layer bytes start with the offset 0xe in the pcapng.
What weird is these ftp packets.Take the fourth packet for example.
This is Kernel module's log.(The /**/ which does not exist in the original data is comment I added for better understanding)
[ 4964.195893] Packet hex dump:
[ 4964.195904] 000000 45 10 00 42 D9 86 40 00 40 06 DD BC C0 A8 01 07 /* dump start from Internet layer */
[ 4964.195953] 000010 C0 A8 01 0B 93 E4 00 15 A5 63 17 A8 92 28 25 E3
[ 4964.195982] 000020 80 18 01 F6 83 97 00 00 01 01 08 0A C0 EC BD AB
[ 4964.196011] 000030 00 08 A7 2F 00 00 00 00 00 00 00 00 00 00 00 00 /* ftp content:0x00 */
[ 4964.196038] 000040 00 00
[ 4964.196045] hex : data[0-3] = 0x00000000
[ 4964.196049] char: data[0-3] =
[ 4964.196052] --------------- findpkt_iwant ------------------
And this is the wireshark captured packet accroding to:
No. Time Source Source Port Destination Destination Port Protocol Length Info
132 14.635575358 192.168.1.7 37860 192.168.1.11 21 FTP 80 Request: USER ftpuser
Frame 132: 80 bytes on wire (640 bits), 80 bytes captured (640 bits) on interface wlp3s0, id 0
Ethernet II, Src: 58:a0:23:05:3b:2e, Dst: 1c:c1:de:65:e5:d4
Internet Protocol Version 4, Src: 192.168.1.7, Dst: 192.168.1.11
Transmission Control Protocol, Src Port: 37860, Dst Port: 21, Seq: 1, Ack: 28, Len: 14
File Transfer Protocol (FTP)
[Current working directory: ]
0000 1c c1 de 65 e5 d4 58 a0 23 05 3b 2e 08 00 45 10 ...e..X.#.;...E. /* # Internet layer starts from the offset 0x0e */
0010 00 42 d9 86 40 00 40 06 dd bc c0 a8 01 07 c0 a8 .B..#.#.........
0020 01 0b 93 e4 00 15 a5 63 17 a8 92 28 25 e3 80 18 .......c...(%...
0030 01 f6 ab 01 00 00 01 01 08 0a c0 ec bd ab 00 08 ................
0040 a7 2f 55 53 45 52 20 66 74 70 75 73 65 72 0d 0a ./USER ftpuser..
As can be seen,the ftp packet's content is 0x00,but whole packet's length is right(above the Internet layer).And all other ftp packets have the same problem. It seems sk_buff don't get the ftp data.
As wireshark can get the correct packets, I don't think it's firewall's queseton.
My quesetons are :
Why all ftp packets' content is all 0x00 while packets' length is correct ?
Where is my ftp data in the struct sk_buff or it's stored in other place?
Is there anyone who has had the same problem?
Any help will be appreciated.
Well i think you got the same situation as me, which you couldn't filter/log any kind of TCP payloads, I was using arch Linux with kernel 5.18.x and I have to recompile the kernel with netfilter TCP packet payload filtering support in order to get it work, another interesting fact is I couldn't use the string match of nftables too, because it JUST DOESN'T WORK!, wireshark has a different story, I think it uses a separated TAP or something else rather than netfilter in order to keep eyes on payloads, at this point I don't exactly remember what kernel options you have to enable in order to get the netfilter TCP payload tracker to work, but give it a search, its all I can help.
And remember (as my experience told me), everytime you got into weird issues like these: getting unexpected null results, or any kind of weird errors that you find them impossible to fix, or make no sense at all, in most cases there must be something related to your kernel (AKA kernel configuration):
for example:
nf_conntrack is null: missing conntrack module
no kernel POST after being booted: missing framebuffer module

Getting UDP Destination Address:Port from TPROXY'd Traffic

I'm trying to get the original destination from UDP packets that have been redirected by an iptables TPROXY rule. However several ways of doing this have failed, and using a raw socket to fish from the IP header seems to give me garbled packets.
The confusion is two fold really. The latter small packet is the UDP payload obtained by SOCK_DGRAM, however changing it to SOCK_RAW returns this garbled mess that contains no traces of the payload, nor IP header.
Wrong stuff:
Port: 0 -- 45 00 00 48 1c ac 00 00 6e 11 7b f6 1b 46 8b 53 8b 63 82 06 69 7d 69 b4 00 34 29 5f 00 ba 03 00 47 20 01 00 30 2b ca 00 01 7d 8d 58 e8 89 88 0e 60 7f ee 00 c0 0b e3 01 00 00 00 00 00 00 00 06 0d e3 01 80 83 06 85 80 received 74 bytes
Correct payload: Port: 0 -- ff ff ff ff 55 4b a1 d5 77 received 9 bytes
A correct raw packet that hasn't been affected by TPROXY looks like:
45-00-00-65-17-4B-40-00-3A-11-46-F8-2D-23-01-BA-4E-9F-64-C9-69-CD-26-8F-00-51-C2-C9-FF-FF-FF-FF-52-4C-20-30-36-2F.....
the FF-FF-FF-FF-5x is the start of the payload that is needed, and the port is there at 69CD.
Having moved to C/C++ socket code because C# didn't seem to have IP_TRANSPARENT flags that were apparently needed for TPROXY to work, I've tried setting socket options for IP_TRANSPARENT, IP_RECVORIGSTDADDR, IP_HDRINCL.
I changed from recvfrom to recvmsg and msghdrs, in order to try cycling through ancillary data to get the sin_port from the sockaddr_in result. I've pieced together lots of attempts from different SO questions, admittedly I don't really know what's going on at this level of socket code, things like cmsghdr, cmsg, msghdr, iovecs etc are all new to me. Nothing seems to work here, and whatever TPROXY is doing to those packets leaves them unusable anyway.
Here's what's grabbing the packet, printing the hex, and trying to get the port (it results in 0 no matter what)
recvlen = recvmsg(fd, &message, 0);
printf("received %d bytes\n", recvlen);
for (cmsghdr *cmsg = CMSG_FIRSTHDR(&message); cmsg != NULL; cmsg = CMSG_NXTHDR(&message, cmsg))
{
if (cmsg->cmsg_level != SOL_IP || cmsg->cmsg_type != IP_ORIGDSTADDR) continue;
printf("copying port\n");
std::memcpy(&dstIpAddr, CMSG_DATA(cmsg), sizeof(sockaddr_in));
dstPort = ntohs(dstIpAddr.sin_port);
}
printf("Port: %i -- ", dstPort);
//std::cout << "Destination port: " << dstPort << std::endl;
for (int i = 0; i < recvlen; i++)
{
printf("%02x ", buf[i]);
}
iptables rules are redirecting packets that match a hex string to the port this socket is bound to:
TPROXY udp -- anywhere anywhere udp dpts:27000:28000 STRING match "|ffffffff54|" ALGO name bm TO 65535 TPROXY redirect 0.0.0.0:29000 mark 0x1/0x1
TPROXY udp -- anywhere anywhere udp dpts:27000:28000 STRING match "|ffffffff55|" ALGO name bm TO 65535 TPROXY redirect 0.0.0.0:29000 mark 0x1/0x1
TPROXY udp -- anywhere anywhere udp dpts:27000:28000 STRING match "|ffffffff56|" ALGO name bm TO 65535 TPROXY redirect 0.0.0.0:29000 mark 0x1/0x1
TPROXY udp -- anywhere anywhere udp dpts:27000:28000 STRING match "|ffffffff57|" ALGO name bm TO 65535 TPROXY redirect 0.0.0.0:29000 mark 0x1/0x1
I just need to get the destination address:port, in order to forward traffic to conditionally forward it to where it was meant to be going, and send the result back. If I can do this using a UDP socket and somehow just get the payload, then get the port from some functions, fab. If I have to get the raw packet then fish it from the IP header, that's fine too, except I can't, because TPROXY seems to be garbling those packets.
I believe I was setting the iov_len to the size of a const char* by doing sizeof(buffer), thus getting essentially no writable space. Upon fiddling with declarations and ending up at this, I obtained the IP and port correctly with the cmsg loop. I still don't know why TPROXY warps the packets when viewing them through a raw socket, which would be interesting to know.
iov.iov_base = cPacket;
iov.iov_len = BUFSIZE;
mHeader.msg_name = &sSourceAddr; //sockaddr_storage
mHeader.msg_namelen = sizeof(struct sockaddr_in);
mHeader.msg_iov = &iov;
mHeader.msg_iovlen = 1;
mHeader.msg_control = cControl;
mHeader.msg_controllen = BUFSIZE;
for (cmsghdr *cmsg = CMSG_FIRSTHDR(&mHeader); cmsg != NULL; cmsg = CMSG_NXTHDR(&mHeader, cmsg))
{
if (cmsg->cmsg_level != SOL_IP || cmsg->cmsg_type != IP_ORIGDSTADDR) continue;
std::memcpy(&sDestIP, CMSG_DATA(cmsg), sizeof(sockaddr_in));
iPort = ntohs(sDestIP.sin_port);
sAddress = sDestIP.sin_addr;
}

PIC32 UART sends garbage characters after initialization

I'm writing code to configure the serial port on a pic32 family device. The initialization appears to work for the most part, but I get garbage data in place of the first 6 characters that I write. I noticed, however, that if I add an arbitrarily long wait at the end of the initialization function, this goes away. Is there some register flag that I need to be waiting on at the end of my initialization? My initialization code is below. If it helps, I am basing this initialization off of the UART section in the pic32 reference manual. I added the code below for my transmission function as well. My expected output string is "Hello from the bootloader code.\r\n" but the actual bytes I get are:
00000000 00 00 aa b1 b1 bd 81 66 72 6f 6d 20 74 68 65 20 |.......from the |
00000010 62 6f 6f 74 6c 6f 61 64 65 72 20 63 6f 64 65 2e |bootloader code.|
00000020 0d 0a
void initializeUART2()
{
uint32 counter;
initialized = TRUE;
U2MODE = 0;
U2STA = 0;
U2BRG = 0;
IEC1bits.U2TXIE = 0;
IEC1bits.U2RXIE = 0;
IEC1bits.U2EIE = 0;
//disable UART transmission before config
U2STA &= ~UART_TRANSMIT_ENABLED_STATUS_FLAG;
//disable UART before config
U2MODE &= ~UART_ENABLED_MODE_FLAG;
RS232_RS485_TRIS=0; //set to output
RS232_RS485=0; //select RS-232 mode on MAX3161
//set baudrate BAUDRATE = CLOCK_FREQUENCY/(16*(U2BRG + 1))
//solve for U2BRG value
U2BRG = (UINT16)(((PERIPHERAL_CLOCK_FREQUENCY/UART2_BAUDRATE)/16)-1);
//set mode to 8 bit no parity
U2MODE &= ~UART_PARITY_DATA_MODE_BITS;
//set number of stop bits to 1
U2MODE &= ~UART_EXTRA_STOP_MODE_BIT_FLAG;
//enable the UART port
U2MODE |= UART_ENABLED_MODE_FLAG;
//enable serial transmission
U2STA |= UART_TRANSMIT_ENABLED_STATUS_FLAG;
//without this loop, I get garbage in first 6 bytes of my first message
counter = 1000;
while(counter--);
}
void putUART2(uint32 value)
{
if(!initialized)
{
initializeUART2();
}
//make sure value is in range of writable values
value &= UINT32_MASK(8);
//clear transmit interrupt flag
IFS1bits.U2TXIF = 0;
//wait for the transmit buffer to be empty
while((U2STA & UART_TRANSMIT_STATUS_FLAG) == 0);
//set the data byte to be written in the write register
//also starts transmission
U2TXREG = value;
//wait for the transmit buffer to be empty
//both of these waits are necessary to avoid missing bytes
while((U2STA & UART_TRANSMIT_STATUS_FLAG) == 0);
}
The MAX3161 needs at least 100 ns to stabilize after switching modes to RS232.
Also, these lines:
RS232_RS485_TRIS=0; //set to output
RS232_RS485=0; //select RS-232 mode on MAX3161
should be reversed; set the output, then the direction register to avoid glitches.
Suspect the MAX3161 chip, which has charge pumps, needs the additional time to reach stable operating voltages.
It may be only for a bit time or 2, but if a message is sent too early, the serial output is messed until a quiet time occurs.
Lesser candidate: problem is an interaction between this and the unposted send routine.
Note: It's amazing how seeing using info like the unposted "garbage data" may help. Also knowing what the "good" first 6 bytes or so is useful.
[Edit] #Doug Currie is on the right track.
When RS232_RS485_TRIS1 is changed to output, a delay time as he suggest is needed before data is sent. This applies here as well as other place in code.
Further, before RS232_RS485_TRIS1 is changed to input, code needs to insure all the data is completely transmitted. This may be a 10/baud after the the PIC declares the xmit buffer empty. Or check the proper xmit status bit before turning the bus around. (Shift Register empty - names vary depending on compiler.)

raw socket send two packets on a virtual Network

I've a problem with my sendto function in my code, when I try to send a raw ethernet packet.
I use a Ubuntu 12.04.01 LTS, with two tap devices connected over two vde_switches and a dpipe
Example:
my send programm create the packet like below, the programm is binded by the socket from tap0 and send the packet to tap1. On tap1 one receiver wait for all packets on socket.
My raw ethernet packet looks so:
destination Addr ____source Addr _________ type/length ___data
00:00:01:00:00:00___00:00:01:00:00:01____ length in Byte__some data
Example packet to send:
00:00:01:00:00:00 00:00:01:00:00:01 (length in byte) (Message)test
but my programm generate two packets, when I look in wireshark:
first packet is an IPX packet and [Malformed Packet] and looks like in hex (data = test)
00 04 00 01 00 06 00 00 01 00 00 01 00 00 00 01 74 65 73 74 00
Linux cooked capture
Packet type: sent by us (4)
Link-layer address type: 1
Link-layer address length: 6
Source: 00:00:01:00:00:01
Protocol: Raw 802.3 (0x0001)
[Malformed Packet: IPX]
second packet unknown protocol
00 00 00 01 00 06 00 00 01 00 00 01 00 00 31 00 74 65 73 74 00
Linux cooked capture
Packet type: Unicast to us (0)
Link-layer address type: 1
Link-layer address length: 6
Source: 00:00:01:00:00:01
Protocol: Unknown (0x3100)
Data
Data: 7465737400
[Length: 5]
outcut from my source code
sock_desc = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
/*struct for sending*/
sock_addr.sll_family = AF_PACKET;
sock_addr.sll_protocol = htons(ETH_P_802_3);
sock_addr.sll_ifindex = if_nametoindex(argv[1]);
sock_addr.sll_hatype = ARPHRD_ETHER; //Ethernet 10Mbps
sock_addr.sll_pkttype = PACKET_HOST; // Paket zu irgendjemand
sock_addr.sll_halen = ETH_ALEN; //6 Oktets in einer ethernet addr
/*MAC Length 8 Oktets*/
sock_addr.sll_addr[0] = frame.src_mac[0];
sock_addr.sll_addr[1] = frame.src_mac[1];
sock_addr.sll_addr[2] = frame.src_mac[2];
sock_addr.sll_addr[3] = frame.src_mac[3];
sock_addr.sll_addr[4] = frame.src_mac[4];
sock_addr.sll_addr[5] = frame.src_mac[5];
/*not in use*/
sock_addr.sll_addr[6] = 0x00;
sock_addr.sll_addr[7] = 0x00;
memset(buffer, '0', sizeof(char)*ETH_FRAME_LEN);
/*set the frame header*/
/*build RAW Ethernet packet*/
buffer[0] = frame.dest_mac[0];
buffer[1] = frame.dest_mac[1];
buffer[2] = frame.dest_mac[2];
buffer[3] = frame.dest_mac[3];
buffer[4] = frame.dest_mac[4];
buffer[5] = frame.dest_mac[5];
buffer[6] = frame.src_mac[0];
buffer[7] = frame.src_mac[1];
buffer[8] = frame.src_mac[2];
buffer[9] = frame.src_mac[3];
buffer[10] = frame.src_mac[4];
buffer[11] = frame.src_mac[5];
while(frame.data[0] != '*'){
printf("Input: ");
scanf("%s", frame.data);
tempLength = 0;
while(frame.data[tempLength] != '\0'){
tempLength++;
}
input = 0;
for(sendLen = 14;sendLen <= (14+tempLength);sendLen++){
buffer[sendLen] = frame.data[input];
input++;
}
sprintf(convLen,"%x", (14 + input));
buffer[12] = convLen[0];
buffer[13] = convLen[1];
length_in_byte = sendto(sock_desc, buffer, 14+input,0,(struct sockaddr*) &sock_addr,sizeof(struct sockaddr_ll));
if(length_in_byte <= 0){
printf("Error beim Senden");
}else{
printf("\n");
printf("src: %02x:%02x:%02x:%02x:%02x:%02x\t->\tdest: %02x:%02x:%02x:%02x:%02x:%02x\n",frame.src_mac[0],frame.src_mac[1],frame.src_mac[2],frame.src_mac[3],frame.src_mac[4],frame.src_mac[5],frame.dest_mac[0],frame.dest_mac[1],frame.dest_mac[2],frame.dest_mac[3],frame.dest_mac[4],frame.dest_mac[5]);
printf("Data: %s\n", frame.data);
}
}
please i need some help to find my mistake.
Thank you forward.
Please give us the lines dealing with the socket creation operation.
I assume you have created your socket like that :
int socket = socket(AF_PACKET,SOCK_RAW,IPPROTO_IP)
You are right when you build the ethernet header (by the way you should use instead struct ethhdr, it's cleaner).
After that you send your data, without putting L4 header and L3 header.... It's normal that your code doesn't work.
I assume you now the OSI Model.
If it's not the case read the paper before reading the next text.
So when you want to create a RAW packet, you have many things to do before.
For example if you want to use TCP/IP protocol you will have to do the next operation
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#DEFINE SIZEMAX 1000
int main() {
char buffer[65535] // MDU
// CREATE YOUR SOCKET
int socket = socket(AF_PACKET,SOCK_RAW,IPPROTO_RAW) ;
// You can also specify some opt to your socket but I let you done your own stuffs
struct ethhdr * ethdr ;
struct iphdr * iph ;
struct tcphdr * tcph;
// Fill all the fields of these last structures (i can't do it for you too long).
// Fill the buffer
memcpy(buffer,ethdr,sizeof(struct ethhdr)) ;
// Deplace it to the good addr
buffer = buffer + sizeof(struct ethhdr) ;
memcpy(buffer,iph,sizeof(struct iphdr)) ;
buffer = buffer + sizeof(struct iphdr)) ;
memcpy(buffer,tcph,sizeof(struct tcphdr)) ;
printf("your entry : \n") ;
char * entry = malloc(SIZEMAX) ;
sncanf("%s",entry,100) ;
buffer = buffer+ 100 ;
memcpy(buffer,entry,100) ;
int size_send = sendto(socket,.......) ;
if(size_send =< 0)
perror("error sending data") ;
return 0 ;
}
This is pseudo-code but it tell you how to send raw packet.
This paper will do the work for you :
RAW Socket TCP/IP
Hope it will help you
Anthony
I think your code is missing the ethernet "packet type ID field". See struct ethhdr in if_ether.h. Now you put convLen where the proto should be. It probably matches the proto number of IPX. Try setting it to something (eg ETH_P_IP) or test what happens when you set it to zero.
I understand you want to make your own protocol and are using the field after the ethernet addresses for the length. However I do suggest you keep at least the ethernet level header standards compliant and build your own on top of that (in the ethernet frame payload). Otherwise youll get problems with tools(like wireshark) and device drivers that try to parse the ethernet headers.
As to why you send two packets, I think the reason lies in the way you scanf input from the user. The while loop is peculiar. I suggest trying to send some data with a fixed input, eg char msg[] = "Test";
Sorry if the answer is vague. It is difficult to help you, since your code is not complete and I can not test it.
OK I see why my receiver receiv two packets. The first packet ist the send by us packet and the second is the Unicast to us. The problem I don't need the first packet to receive. I have test my code and have one capture with the two packets as example.
First frame in hex code from Wireshark:
0004 0001 0006 0000010000020000 0060 the message
Second frame:
0000 0001 0006 0000010000020000 1234 the message
This is Linux cooked capture an means:
2 Bytes packet typ // 0 = To us; 1 = Broadcast; 2 = Multicast; 3 = from somebody to somebody; 4 = sent by us
2 Bytes LINUX ARPHDR_ value
2 Bytes Link layer addr. lenght
8 Bytes source address
2 Bytes Ethernet protocol //e.g. 1 Novell 802.3 without 802.2 header; 4 frames with 802.2 header
My questions:
First is it possible to filter or ignore the first packet?
Second why contains the first packet the protocol typ from the send structur and the second packet the protocol typ from buffer?
Example:
For the first packet
sock_addr.sll_family = AF_PACKET;
sock_addr.sll_protocol = htons(0x0060);
sock_addr.sll_ifindex = 3;
sock_addr.sll_hatype = ARPHRD_ETHER;
sock_addr.sll_pkttype = PACKET_HOST;
sock_addr.sll_halen = ETH_ALEN;
/*MAC Length 8 Oktets*/
sock_addr.sll_addr[0] = 0x00;
sock_addr.sll_addr[1] = 0x00;
sock_addr.sll_addr[2] = 0x01
sock_addr.sll_addr[3] = 0x00;
sock_addr.sll_addr[4] = 0x00;
sock_addr.sll_addr[5] = 0x02;
/*not in use*/
sock_addr.sll_addr[6] = 0x00;
sock_addr.sll_addr[7] = 0x00;
for second packet the buffer like 802.3 frame
buffer[0-5] = 0x00 0x00 0x01 0x00 0x00 0x03 // Destination address
buffer[6-11] = 0x00 0x00 0x01 0x00 0x00 0x02 // Source address
buffer[12-13] = 0x12 0x34 // Protocol dummy typ
My receiver can capture the first packet without a connection between two vde_switches and when I connect the switches with dpipe and vde_plug can I capture the second packet too.

Build a tcp packet with libnet get incorrect tcp flags and window size

I followed the synflood.c in "Hacking: the art of exploitation", which build a tcp packet with libnet_build_tcp.
if (libnet_build_tcp(
libnet_get_prand(LIBNET_PRu16),
dest_port,
libnet_get_prand(LIBNET_PRu32),
libnet_get_prand(LIBNET_PRu32),
TH_SYN,
libnet_get_prand(LIBNET_PRu16),
0,
NULL,
0,
packet+LIBNET_IP_H) == -1)
printf("Build tcp packet failed");
It looks well... But when I use wireshark or tcpdump to examine the tcp
packets it create, I get:
20:58:10.722180 IP 91.114.233.61.63812 > 172.17.170.79.80: tcp 20 [bad hdr length 0 - too short, < 20]
In wireshark I found a tcp packet(last 20 bytes).
0000 08 00 27 f3 fc 9e e8 39 df 08 f4 fb 08 00 45 10 ..'....9 ......E.
0010 00 28 56 46 00 00 96 06 aa f5 b2 09 1b 1a ac 11 .(VF.... ........
0020 aa 4f 0c 8c 00 50 56 46 00 00 67 d4 65 32 00 00 .O...PVF ..g.e2..
0030 00 00 75 74 55 4f
It looks like where should be tcpflags become zeros and the window size zeros too.
I tried to modify the advised window size when built tcp packet, but still get zeros.
Any instruction?
PS: I examined it more and find in my 64 bit unix machine, libnet will give 8 bytes to seq and ack, which makes things strange...
the libnet source for libnet_build_tcp is here
int
libnet_build_tcp(u_short sp, u_short dp, u_long seq, u_long ack, u_char control,
u_short win, u_short urg, const u_char *payload, int payload_s,
u_char *buf)
{
struct libnet_tcp_hdr tcp_hdr;
if (!buf)
{
return (-1);
}
tcp_hdr.th_sport = htons(sp); /* source port */
tcp_hdr.th_dport = htons(dp); /* destination port */
tcp_hdr.th_seq = htonl(seq); /* sequence number */
tcp_hdr.th_ack = htonl(ack); /* acknowledgement number */
tcp_hdr.th_flags = control; /* control flags */
tcp_hdr.th_x2 = 0; /* UNUSED */
tcp_hdr.th_off = 5; /* 20 byte header */
tcp_hdr.th_win = htons(win); /* window size */
tcp_hdr.th_sum = 0; /* checksum done in userland */
tcp_hdr.th_urp = urg; /* urgent pointer */
if (payload && payload_s)
{
/*
* Unchecked runtime error for buf + TCP_H + payload to be greater
* than the allocated heap memory.
*/
memcpy(buf + LIBNET_TCP_H, payload, payload_s);
}
memcpy((u_char *)buf, (u_char *)&tcp_hdr, sizeof(tcp_hdr));
return (1);
}
Solved
Sorry, I checked the libnet-headers rather than the libnet-1.0-headers, it defines
struct libnet_tcp_hdr
{
u_short th_sport; /* source port */
u_short th_dport; /* destination port */
u_long th_seq; /* sequence number */
u_long th_ack;
in 64 bit machine long int will occupy 8 bytes. I know what happened.

Resources