Read TCP message with CAPL - tcp

I am trying to read a message via TCP.
variables
{
dword serverIpAddress = 0x0101A8C0;
dword serverPort = 502;
dword clientIpAddress = 0x0201A8C0;
dword size = 2;
int varRead_AI;
char Read_AI_receive[1024];
long Read_AI_TCP;
long result_Read_AI;
byte Read_AI[12]= {0,0,0,0,0,6,1,3,0,1,0,0};
}
TcpSend(gConnectionSocket,Read_AI,elcount(Read_AI)); // send the request
// void OnTcpReceive( dword socket, long result, dword address, dword port, char buffer[], dword size)
void OnTcpReceive(dword gConnectionSocket, long result_Read_AI, dword serverIpAddress, dword serverPort, char Read_AI_receive[], dword size)
{
write("result_Read_AI: %d",result_Read_AI);
}
Which values do I have to give the function and does the function returns the result (in the varible result) for every TCP message which comes in?

Related

Arduino's Serial port need a println to read

I need to use the method Serial.println() to read the serial buffer correctly. Without Serial.println() it does not read it.
A frame is received, which has a sync byte, a byte that is the sender address, a byte that is the destination address and a data byte
void client(){
String string, ax,aux;
char ax1,ax2,ax3,ax4;
string="";
ax="o1"; //the character is for frame synchronization and 1 is the client's address
aux="";
while (Serial.available() > 0) {
char c= Serial.read();
string=string+c;
Serial.println(c); //without this line the code does not work
}
aux=string;
ax1=string[0]; //sync byte
string="";;
string=aux;
ax2=string[1]; //sender address byte
string="";;
string=aux;
ax3=string[2];// destination address byte
string="";;
string=aux;
ax4=string[3]; //data byte
string="";;
string=aux;
Serial.println(string); //without this line the code does not work
if (ax1==ax[0] && ax3==ax[1] && ax4=='1'){
digitalWrite(A0,HIGH);
}
if (ax1==ax[0] && ax3==ax[1] && ax4=='0'){
digitalWrite(A0,LOW);
}
}

How i can Send TCP Raw Socket with Ip Flags and Tcp Control Flags

I try to programm a Code which is able to build and send raw Sockets with the ability to fill all Fields in the IP Header and TCP Header.
I can actualy set all field for tcp header.
If i set the IP Flags
short int ip_moreFrag :1, ip_doNotFrag:1, ip_reserved : 1;
to 0and follow the packet in Wireshark, i see that all the Fields i set is set too. enter image description here
But if i set the Ip Flags to 1 and follow the packet on Wireshark, i can see that the Protokol of my packet changed to Ipv4 and the flags are not set in Wireshark. Wireshark IPv4 Protokol Why?
I could not find the isue why the Programm is not send tcp packets if i set one of the ip flags to 1.
Could you help me out?
Here is my Code:
// Run as root or SUID 0,
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
// Packet length
#define PCKT_LEN 8192
struct ipheader {
unsigned char ip_hl :4, ip_v :4;
unsigned char ip_tos :8;
unsigned short int ip_len :16;
unsigned short int ip_id :16;
unsigned short int ip_off :13;
unsigned short int ip_moreFrag :1, ip_doNotFrag:1, ip_reserved : 1;
unsigned char ip_ttl :8;
unsigned char ip_p :8;
unsigned short int ip_sum :16;
unsigned int iph_sourceip :32;
unsigned int iph_destip :32;
};
/* Structure of a TCP header */
struct tcpheader {
unsigned short int th_sport :16;
unsigned short int th_dport :16;
unsigned int th_seq :32;
unsigned int th_acknum :32;
unsigned char th_reserved :4, th_off :4;
unsigned short int th_fin :1, th_syn :1, th_rst :1, th_psh :1, th_ack :1,
th_urg :1, th_cwr :1, th_ece :1;
unsigned short int th_win :16;
unsigned short int th_sum :16;
unsigned short int th_urp :16;
};
unsigned short csum(unsigned short *buf, int len) {
unsigned long sum;
for (sum = 0; len > 0; len--)
sum += *buf++;
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return (unsigned short) (~sum);
}
int main(int argc, char *argv[]) {
int sd;
// No data, just datagram
char buffer[PCKT_LEN];
// The size of the headers
struct ipheader *ip = (struct ipheader *) buffer;
struct tcpheader *tcp = (struct tcpheader *) (buffer
+ sizeof(struct ipheader));
struct sockaddr_in sin, din;
int one = 1;
const int *val = &one;
memset(buffer, 0, PCKT_LEN);
sd = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
if (sd < 0) {
perror("socket() error");
exit(-1);
} else
printf("socket()-SOCK_RAW and tcp protocol is OK.\n");
// The source is redundant, may be used later if needed
// Address family
sin.sin_family = AF_INET;
din.sin_family = AF_INET;
// Source port, can be any, modify as needed
sin.sin_port = htons(atoi("1000"));
din.sin_port = htons(atoi("1000"));
// Source IP, can be any, modify as needed
sin.sin_addr.s_addr = inet_addr("1.2.3.4");
din.sin_addr.s_addr = inet_addr("127.0.0.1");
// IP structure
ip->ip_v = 4;
ip->ip_hl = 5;
ip->ip_tos = 16;
ip->ip_off = 0;
ip->ip_reserved = 0;
ip->ip_doNotFrag = 0;
ip->ip_moreFrag = 0;
ip->ip_len = htons(sizeof(struct ipheader) + sizeof(struct tcpheader));
ip->ip_id = htons(54321);
ip->ip_ttl = 255;
ip->ip_p = 6; // TCP
ip->ip_sum = 0; // Done by kernel
ip->iph_sourceip = inet_addr("1.2.3.4");
ip->iph_destip = inet_addr("127.0.0.1");
tcp->th_sport = htons(atoi("1000"));
tcp->th_dport = htons(atoi("1000"));
tcp->th_seq = htonl(0);
tcp->th_acknum = 0;
// tcp->th_hlen = 4;
tcp->th_reserved = 0;
tcp->th_off = 5;
tcp->th_fin = 1;
tcp->th_syn = 1;
tcp->th_rst = 1;
tcp->th_psh = 1;
tcp->th_ack = 1;
tcp->th_urg = 1;
tcp->th_cwr = 1;
tcp->th_ece = 1;
tcp->th_win = htons(32767);
tcp->th_sum = 0; // Done by kernel
tcp->th_urp = 0;
// IP checksum calculation
ip->ip_sum = htons(
csum((unsigned short *) buffer,
(sizeof(struct ipheader) + sizeof(struct tcpheader))));
// Inform the kernel do not fill up the headers' structure, we fabricated our own
if (setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0) {
perror("setsockopt() error");
exit(-1);
} else
printf("setsockopt() is OK\n");
unsigned int count;
if (sendto(sd, buffer, ip->ip_len, 0, (struct sockaddr *) &din, sizeof(din))
< 0)
// Verify
{
perror("sendto() error");
exit(-1);
} else
printf("Count #%u - sendto() is OK\n", count);
close(sd);
return 0;
}
Your program assumes that your compiler arranges bitfields from least-significant to most-significant within a 2-byte unit for these structure members:
unsigned short int ip_off :13;
unsigned short int ip_moreFrag :1, ip_doNotFrag:1, ip_reserved : 1;
but Wireshark shows that that assumption is incorrect. If you look at your second packet capture where, apparently, two of the ip_moreFrag, ip_doNotFrag and ip_reserved members are set to 1 you'll see that Wireshark does not show any of the corresponding R, DF or MF flag bits set in the IP header. Those flag bits are all 0 in the packet.
Instead, setting those bitfields caused two bits to be set to 1 in the Fragment offset field. That causes Wireshark to believe that this packet contains only a fragment of a larger datagram, and that the data in this packet that follows its IP header belongs at position 768 in the larger datagram. Data at position 768 can not be a TCP header (the TCP header would be found at position 0) and therefore Wireshark does not interpret any of the data in this packet as a TCP header.
To fix, you can either reorder the bitfields in your struct ipheader so that they map to the correct position in the on-the-wire header, or you can switch to a different technique that doesn't depend on bitfields for building the header. Using bitfields is fragile, because compilers have a lot of freedom in how they arrange bitfields in memory. Even if you manage to get the bitfield mechanism working with the compiler you're using right now, there's no guarantee that it will work the same way with a different compiler or with a different release of your current compiler or with an invocation of your compiler with different compilation options.
If you decide to continue with bitfields then you should check that the TCP flag bits in your struct tcpheader are doing what you need. They might or might not match up with the correct bits in the on-the-wire format. All you know from that first packet capture is that if you set them all to 1 then you get 0xff in the flag field, but you don't know for sure that the various structure members control the right bits. For instance, try setting just th_syn to 0 and see if Wireshark agrees that the SYN flag has been turned off.

Arduino reading json from EEPROM / converting uint8_t to char

I'm using ArduinoJSON to write a couple of data points to my EEPROM on Arduino Uno. I'm running into a problem with getGroundedPR where I need to convert a uint8_t to a char to pass retrieved data into my JSON parser.
This is my first time using EEPROM so I'm willing to bet there's a better way to do this. Should I continue to use JSON or is there a better way? I'm being cautious of the 10k write limit (give or take) on the EEPROM.
the EEPROM read/write is commented out until I have my process nailed down
void IMUController::setGroundedPR(double p, double r) {
Serial.print("Setting IMU ground: ");
StaticJsonBuffer<200> jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
root["pitch"] = p;
root["roll"] = r;
root.printTo(Serial);
char buffer[256];
root.printTo(buffer, sizeof(buffer));
Serial.println();
// EEPROM.write(EEPROM_ADDRESS_IMU_GROUNDED, buffer);
}
double* IMUController::getGroundedPR() {
double ret[2] = {0, 0};
StaticJsonBuffer<200> jsonBuffer;
uint8_t json_saved = EEPROM.read(EEPROM_ADDRESS_IMU_GROUNDED);
char json[] = "asdf"; // convert json_saved to char here
JsonObject& root = jsonBuffer.parseObject(json);
if(!root.success()) {
// return the result
ret[0] = (double)root["pitch"];
ret[1] = (double)root["roll"];
return ret;
}
return ret;
}
The EEPROM functions read() and write() only deal with a single character. You need to use put() and get() to deal with arrays.
char buffer[256];
root.printTo(buffer, sizeof(buffer));
EEPROM.put(EEPROM_ADDRESS_IMU_GROUNDED, buffer);
And to read it back:
char json[256];
EEPROM.get(EEPROM_ADDRESS_IMU_GROUNDED, json);
JsonObject& root = jsonBuffer.parseObject(json);
You need to take care with he array sizes though, the EEPROM functions will get and put the number of bytes in the array (256). The string should be null terminated so the extra bytes shouldn't cause a problem.

Detect pattern in incoming byte stream

I would like to detect a certain byte pattern in an incoming byte stream at the UART. I am using Arduino. Currently, the code detects a single \r character. On this character is detected, the byte stream before this character gets stored into a buffer. This is easy. This is my code;
int incomingByte = 0; // for incoming serial data
void setup() {
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
}
void loop() {
// send data only when you receive data:
if (Serial.available() > 0 ) {
// read the incoming byte:
incomingByte = Serial.read();
if (incomingByte != '\r') {
buffer_incoming_data[index_buffer]=incomingByte;
index_buffer++;
} else {
index_buffer = 0;
}
}
}
Here is my problem. Instead of a single character \r, I would like to detect a byte pattern that looks like this 0xAA 0xBB 0xCC. When this byte pattern is detected, the byte stream before byte pattern gets stored into a buffer.
Guess you invoke loop() method inside real loop operator. I can suggest next way:
int incomingByte = 0; // for incoming serial data
int pattern [] = {0xAA, 0xBB, 0xCC};
int patternIndex = 0;
int patternSize = sizeof(pattern)/sizeof(pattern[0]);
void loop() {
// send data only when you receive data:
if (Serial.available() > 0 ) {
// read the incoming byte:
incomingByte = Serial.read();
if(pattern[patternIndex] != incomingByte){
// if we found begin of pattern but didn't reach the end of it
if(patternIndex>0){
for(int i=0; i<=patternIndex-1; i++){
buffer_incoming_data[index_buffer]=pattern[i];
index_buffer++;
}
}
patternIndex = 0;
}
if(pattern[patternIndex] == incomingByte){
patternIndex++;
}else{
buffer_incoming_data[index_buffer]=incomingByte;
index_buffer++;
}
//if we reached the end of pattern
if(patternIndex==patternSize){
//do something with buffer
patternIndex = 0;
index_buffer = 0;
}
}
}
As you can see, I didn't check index_buffer for "index out of range" exception, but you should. Hope I helped you.

parse IP and TCP header (especially common tcp header options)of packets captured by libpcap

I want to use libpcap to capture IP packet, and the I want to parse the IP header and tcp header.
`
there are IP header and TCP header structures in <netinet/ip.h> and <netinet/tcp.h>
IP header is relatively easier to parse, but for TCP header,since there are tcp options,
the common options are MSS, SACK(selective acknowledgement), timestamp, window scaling and NOP.
I want to have a function parse_pkt():
struct tcphdr tcp_hdr;
struct ip ip_hdr;
parse_pkt(u_char *pcap_packet, struct ip* p_ip, struct tcp* p_tcp);
so after calling the function, if I want to know the source ip address, sequence number, and MSS,
scr_ip = ip_hdr.src_ip
seq = tcp_hdr.seq
mss = tcp_hdr.mss
are there any similar source codes/snippets which can satisfy my requirements?
thanks!
(First example below) Here's something that I have in the works (in C++11). This is for UDP packets, but you could adapt it for TCP packets by adding the related struct and Net::load() template like the one below.
(Second example below) You didn't specify a target language in the question, but if you're looking for C, then you might use #pragma pack on the structures and then cast the pointer+offset as a pointer to the struct and then call ntohs/ntohl on the appropriate fields. Doing that is probably the fastest solution, but it relies on #pragma pack, which is not standard.
C++11 style
net.h:
namespace Net {
using addr_t = uint32_t;
using port_t = uint16_t;
struct ether_header_t {
uint8_t dst_addr[6];
uint8_t src_addr[6];
uint16_t llc_len;
};
struct ip_header_t {
uint8_t ver_ihl; // 4 bits version and 4 bits internet header length
uint8_t tos;
uint16_t total_length;
uint16_t id;
uint16_t flags_fo; // 3 bits flags and 13 bits fragment-offset
uint8_t ttl;
uint8_t protocol;
uint16_t checksum;
addr_t src_addr;
addr_t dst_addr;
uint8_t ihl() const;
size_t size() const;
};
class udp_header_t {
public:
port_t src_port;
port_t dst_port;
uint16_t length;
uint16_t checksum;
};
template< typename T >
T load( std::istream& stream, bool ntoh = true );
template<>
ip_header_t load( std::istream& stream, bool ntoh );
template<>
udp_header_t load( std::istream& stream, bool ntoh );
std::string to_string( const addr_t& addr );
}
net.cpp:
namespace Net {
uint8_t ip_header_t::ihl() const {
return (ver_ihl & 0x0F);
}
size_t ip_header_t::size() const {
return ihl() * sizeof(uint32_t);
}
template<>
ip_header_t load( std::istream& stream, bool ntoh ) {
ip_header_t header;
stream.read((char*)&header.ver_ihl, sizeof(header.ver_ihl));
stream.read((char*)&header.tos, sizeof(header.tos));
stream.read((char*)&header.total_length, sizeof(header.total_length));
stream.read((char*)&header.id, sizeof(header.id));
stream.read((char*)&header.flags_fo, sizeof(header.flags_fo));
stream.read((char*)&header.ttl, sizeof(header.ttl));
stream.read((char*)&header.protocol, sizeof(header.protocol));
stream.read((char*)&header.checksum, sizeof(header.checksum));
stream.read((char*)&header.src_addr, sizeof(header.src_addr));
stream.read((char*)&header.dst_addr, sizeof(header.dst_addr));
if( ntoh ) {
header.total_length = ntohs(header.total_length);
header.id = ntohs(header.id);
header.flags_fo = ntohs(header.flags_fo);
header.checksum = ntohs(header.checksum);
header.src_addr = ntohl(header.src_addr);
header.dst_addr = ntohl(header.dst_addr);
}
return header;
}
template<>
udp_header_t load( std::istream& stream, bool ntoh ) {
udp_header_t header;
stream.read((char*)&header.src_port, sizeof(header.src_port));
stream.read((char*)&header.dst_port, sizeof(header.dst_port));
stream.read((char*)&header.length, sizeof(header.length));
stream.read((char*)&header.checksum, sizeof(header.checksum));
if( ntoh ) {
header.src_port = ntohs(header.src_port);
header.dst_port = ntohs(header.dst_port);
header.length = ntohs(header.length);
header.checksum = ntohs(header.checksum);
}
return header;
}
}
Client code in packet capture handler:
using std::chrono::seconds;
using std::chrono::microseconds;
using clock = std::chrono::system_clock;
using Net::ether_header_t;
using Net::ip_header_t;
using Net::udp_header_t;
auto packet_time = clock::time_point(seconds(header->ts.tv_sec) + microseconds(header->ts.tv_usec));
std::istringstream stream(std::string((char*)packet, header->caplen));
stream.seekg(sizeof(ether_header_t), std::ios_base::beg);
auto ip_header = Net::load<ip_header_t>(stream);
if( ip_header.size() > 20 ) {
stream.seekg(ip_header.size() + sizeof(ether_header_t), std::ios_base::beg);
}
auto udp_header = Net::load<udp_header_t>(stream);
alternative (C style):
(Sorry for any errors. I typed this from memory, and didn't try to compile or run--but I think you will understand the basic idea):
net.h:
typedef uint32_t addr_t;
typedef uint16_t port_t;
#pragma pack(push, 1)
typedef struct {
uint8_t dst_addr[6];
uint8_t src_addr[6];
uint16_t llc_len;
} ether_header_t;
typedef struct {
uint8_t ver_ihl; // 4 bits version and 4 bits internet header length
uint8_t tos;
uint16_t total_length;
uint16_t id;
uint16_t flags_fo; // 3 bits flags and 13 bits fragment-offset
uint8_t ttl;
uint8_t protocol;
uint16_t checksum;
addr_t src_addr;
addr_t dst_addr;
} ip_header_t;
typedef struct {
port_t src_port;
port_t dst_port;
uint16_t length;
uint16_t checksum;
} udp_header_t;
#pragma pack(pop)
client code in packet handler:
ip_header_t ip_header = (ip_header_t)*(packet + sizeof(ether_header_t));
ip_header.total_length = ntohs(ip_header.total_length);
ip_header.id = ntohs(ip_header.id);
ip_header.flags_fo = ntohs(ip_header.flags_fo);
ip_header.checksum = ntohs(ip_header.checksum);
ip_header.src_addr = ntohl(ip_header.src_addr);
ip_header.dst_addr = ntohl(ip_header.dst_addr);
int ip_size = 4 * (ip_header.ver_ihl & 0x0F);
udp_header_t udp_header = (udp_header_t)*(packet + ip_size + sizeof(ether_header_t));
udp_header.src_port = ntohs(udp_header.src_port);
udp_header.dst_port = ntohs(udp_header.dst_port);
udp_header.length = ntohs(udp_header.length);
udp_header.checksum = ntohs(udp_header.checksum);
TCP Header Notes
according to netinet/tcp.h, the TCP header is roughly:
typedef struct {
uint16_t src_port;
uint16_t dst_port;
uint32_t seq;
uint32_t ack;
uint8_t data_offset; // 4 bits
uint8_t flags;
uint16_t window_size;
uint16_t checksum;
uint16_t urgent_p;
} tcp_header_t;
Load this struct into memory using whichever method you prefer and don't forget to fix the byte ordering (ntohs/ntohl) for multi-byte integer types as above.
The TCP options follow, which cannot be loaded into a struct like this. See the section about TCP options at this link. For MSS, you will want to parse each option until you find option with kind == 2. Building on the C example above:
typedef struct {
uint8_t kind;
uint8_t size;
} tcp_option_t;
uint16_t mss;
uint8_t* opt = (uint8_t*)(packet + ip_size + sizeof(ether_header_t) + sizeof(tcp_header_t))
while( *opt != 0 ) {
tcp_option_t* _opt = (tcp_option_t*)opt;
if( _opt->kind == 1 /* NOP */ ) {
++opt; // NOP is one byte;
continue;
}
if( _opt->kind == 2 /* MSS */ ) {
mss = ntohs((uint16_t)*(opt + sizeof(opt)));
}
opt += _opt->size;
}

Resources