raw socket send two packets on a virtual Network - c

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.

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;
}

MAX77651 Can't read register with i2c

I am trying to test the i2c communication of the MAX77651 chip before programming it.
So here is my setup to do so:
I have an UMFT4222ev connected to my Linux laptop by USB. This chip has his SCL and SDA linked to the SDA and SCL of my MAX77651 thanks to the Evaluation Kit for the MAX77651. My MAX77651evkit is powered with 3,7V on the Vbatt pin.
I also installed the mraa librarie from git hub and the libft4222. I know mraa is well installed because i tried it with and example.
I was told that the mraa library takes in charge the setup of the FT4222 so i only used mraa functions to make my program.
I searched on the website of Maxim integrated the i2c slave address and one register where i could read data and check if everyting is working. I then read the i2c protocol of communication to read a single register which is available here : https://datasheets.maximintegrated.com/en/ds/MAX77650-MAX77651.pdf at the page 78.
With all those informations I tried to make my "test program". I solved the compiling errors but when I execute the program I can't get what is in the register which should be 0xFF.
Here is my program:
#include "stdio.h"
#include "syslog.h"
#include "string.h"
#include "unistd.h"
#include "mraa/i2c.h"
#include "mraa.h"
#define I2C_ADDR 0x48
int
main(int argc, char *argv[])
{
uint8_t *message;
*message=0XAC;
int i,j,k;
char reg_a_lire = 0x06;
mraa_init();
mraa_i2c_context i2c;
i2c = mraa_i2c_init(0);
mraa_i2c_frequency(i2c,MRAA_I2C_FAST);
mraa_i2c_address(i2c, I2C_ADDR);
mraa_i2c_write_byte(i2c,0x90);
mraa_i2c_read(i2c, message,1);
mraa_i2c_write_byte(i2c,reg_a_lire);
mraa_init();
mraa_i2c_write_byte(i2c,0x91);
mraa_i2c_read(i2c, message,1);
mraa_i2c_read(i2c, message,1);
printf("%02X \n", *message);
mraa_i2c_stop(i2c);
return 0;
}
Here is the actual output :
alex#cyclonit-laptop ~/Test_alex/tests $ ./a.out
AC
And i would like to get FF instead of AC.
I think my error could come from something i missed to initialize the FT4222 or from the MAX77651 which I maybe did nt power up correctly and its not sufficient to put 3,7V on Vbatt. But maybe this is a problem with my program because i don't know much about uint8_t and I made something wrong.
I am hoping someone has experience with FT4222 and/or MAX77651 and can help me.
I think you are confused by pg. 75 of the MAX77651 datasheet.
ADDRESS | 7-BIT SLAVE ADDRESS | 8-BIT WRITE ADDRESS | 8-BIT READ ADDRESS
Main Address | 0x48, 0b 100 1000 | 0x90, 0b 1001 0000 | 0x91, 0b 1001 0001
(ADDR = 1)* | | |
-------------+---------------------+---------------------+-------------------
Main Address | 0x40, 0b 100 0000 | 0x80, 0b 1000 0000 | 0x81, 0b 1000 0001
(ADDR = 0)* | | |
Depending on your view of the I²C specification, you either use the 7-bit address or use both 8-bit addresses. The reason is that the first I²C transaction sends the following 8 bit:
76543210
\_____/\-- R/#W
\------ 7-bit Slave Address
In your case that's 0x48 shifted one bit to the left followed by either a 1 for read mode or a 0 for write mode. Notice that
(0x40 << 1) | 0x00 == 0x80 == 8-bit Write Address (ADDR = 0)
(0x40 << 1) | 0x01 == 0x81 == 8-bit Read Address (ADDR = 0)
(0x48 << 1) | 0x00 == 0x90 == 8-bit Write Address (ADDR = 1)
(0x48 << 1) | 0x01 == 0x91 == 8-bit Read Address (ADDR = 1)
Some people like to use the slave address while other people prefer to give separate addresses so it's clear what the first byte of communication will look like.
So you should remove the extraneous mraa_i2c_write_byte(i2c, ...); lines from your code, as their intention seems to be to send the read or write address to the slave.
Check out the MRAA library API reference. There are functions that abstract reading and writing registers, either byte-wide [8-bit] registers or word-wide [16-bit] registers:
mraa_i2c_read_byte_data
mraa_i2c_read_bytes_data
mraa_i2c_write_byte_data
In both cases you should check the return codes to know if the action succeeded. In your case, your message is likely not altered, because there was a stop/error condition beforehand, because the slave did either not ACK its slave address or it did not ACK the 0x90/0x91 data bytes you mistakenly sent, as they don't show up in the Programmer's Guide as valid addresses.
Another issue is that you try to read register INTM_GLBL (0x06; Global Interrupt Mask Register) using two consecutive read operations. I'm not sure if your intention is to read register 0x06 twice or if you intended to read INT_M_CHG (0x07; Global Interrupt Mask for Charger), because that's not what it will do. Notice the description on pg. 78 of the datasheet:
Note that when the MAX77650/MAX77651 receive a stop
they do not modify their register pointer.
This is typical behavior for I²C slaves that support multi-byte/sequential reads. You will have to issue a sequential read operation for multiple bytes of data if you want to read multiple registers, e.g. using mraa_i2c_read_bytes_data.
Something like the following might get you on the right track. It is supposed to read the CID and CLKS settings and wait forever if a read error occurred. If successful, it will disable charging, all outputs, setup the red LED to blink once every other second and -- as soon as you uncomment it -- transition the On/Off Controller into On Via Software state to enable bias and the LED.
#define MAX77651_SLA 0x48u
#define CNFG_GLBL_REG 0x10u
#define CID_REG 0x11u
#define CNFG_CHG_B_REG 0x19u
#define CNFG_SBB0_B_REG 0x2Au
#define CNFG_SBB1_B_REG 0x2Cu
#define CNFG_SBB2_B_REG 0x2Eu
#define CNFG_LDO_B_REG 0x39u
#define CNFG_LED1_A_REG 0x41u
#define CNFG_LED1_B_REG 0x44u
#define CNFG_LED_TOP_REG 0x46u
int main(int argc, char *argv[]) {
uint8_t data;
int res;
mraa_init();
mraa_i2c_context i2c0;
i2c0 = mraa_i2c_init(0);
mraa_i2c_frequency(i2c0, MRAA_I2C_STD);
mraa_i2c_address(i2c0, MAX77651_SLA);
res = mraa_i2c_read_byte_data(i2c0, CID_REG);
if (res < 0) {
printf("Reading CID_REG failed.\n");
mraa_i2c_stop(i2c0);
while(1);
}
data = res;
printf("CID_REG: CLKS = %02X CID = %02X\n", ((data & 0x70u) >> 4), (data & 0x0Fu));
/* you should check return values here */
mraa_i2c_write_byte_data(i2c0, 0x00u /* CHG_EN = off */, CNFG_CHG_B_REG);
mraa_i2c_write_byte_data(i2c0, 0x04u /* EN_LDO = off */, CNFG_LDO_B_REG);
mraa_i2c_write_byte_data(i2c0, 0x04u /* EN_SBB0 = off */, CNFG_SBB0_B_REG);
mraa_i2c_write_byte_data(i2c0, 0x04u /* EN_SBB1 = off */, CNFG_SBB1_B_REG);
mraa_i2c_write_byte_data(i2c0, 0x04u /* EN_SBB2 = off */, CNFG_SBB2_B_REG);
/* set up red led to toggle every second */
mraa_i2c_write_byte_data(i2c0, 0x17u /* P = 1s, D = 50% */, CNFG_LED1_B_REG);
mraa_i2c_write_byte_data(i2c0, 0x98u /* FS = 6.4mA, BRT = 5.0mA */, CNFG_LED1_A_REG);
mraa_i2c_write_byte_data(i2c0, 0x01u /* EN_LED_MSTR = on */, CNFG_LED_TOP_REG);
// DANGER ZONE: enable only when you know what this is supposed to do
//mraa_i2c_write_byte_data(i2c0, 0x10u /* SBIA_EN = on, SBIA_LPM = normal */, CNFG_GLBL_REG);
mraa_i2c_stop(i2c0);
while(1);
}
I managed to read I2C registers of MAX77651.
First looking at the hardware part I had to make sure that VIO had the right voltage like #FRob said in hid comment.
Then for the software, I stopped using the mraa library because i could'nt control everything. I used the FT4222 library which allowed me to open and initiate the FT4222 device. I took some part of the I2C example in this library for the initialization of the device. Then I noticed that I had to first use the FT4222's write function to send the register i wanted to read , then simply use the read function to get my result. Those are the two steps required.
I won't post the whole program i made as it is mainly taken from the I2C example for initialization but here is the part I added to read my register 0X06 which is supposed to contain 0xFF:
uint8 resultat=0x11;
uint8 *p_resultat=&resultat;
int chiffre;
slaveAddr
uint16 bytesToWrite2 = 1;
uint16 bytesWritten2=1;
uint8 valeur= 0x06; // REGISTER TO READ
uint8 *p_valeur=&valeur;
FT4222_I2CMaster_Write(ftHandle,slaveAddr,
p_valeur,bytesToWrite2,&bytesWritten); //INDICATES WHICH REGISTER TO
// READ
chiffre = FT4222_I2CMaster_Read(ftHandle,
slaveAddr,p_resultat,1, &bytesRead); // READ REGISTER
printf("The content of the register %02X is : %02X \n " ,
valeur,resultat); // DISPLAY RESULT
printf("reading success if : %d = 0 \n " , chiffre);
// READING SUCCESS ?
With this code and the initialization i get the following result :
alex#cyclonit-laptop ~/Downloads/libft4222-1.2.1.4/examples $ ./a.out
Device 0 is interface A of mode-0 FT4222H:
0x0403601c FT4222 A
Chip version: 42220200, LibFT4222 version: 01020104
The content of the register 06 is : FF
reading success if : 0 = 0
Skipping interface B of mode-0 FT4222H.
If someone has the same problem you are free to ask me your question by answering this post.I am very thankful to the people here who helped me!

Modbus TCP - Arduino

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 :)

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