I am not receiving anything in buffer. Wherever I printf my buffer, it is always empty or shows garbage value. Can anyone help?
I defined header, packet and called them in my main, but buffer still shows garbage.
#include <stdint.h>
struct header {
uint16_t f1;
uint16_t f2;
uint32_t f3;
};
struct data {
uint16_t pf1;
uint64_t pf2;
};
#include <arpa/inet.h>
#include <string.h>
#include <stdint.h>
#include "packet.h"
void htonHeader(struct header h, char buffer[8]) {
uint16_t u16;
uint32_t u32;
u16 = htons(h.f1);
memcpy(buffer+0, &u16, 2);
printf("Value of buff is: %hu\n",buffer);
u16 = htons(h.f2);
memcpy(buffer+2, &u16, 2);
u32 = htonl(h.f3);
memcpy(buffer+4, &u32, 4);
}
void htonData(struct data d, char buffer[10]) {
uint16_t u16;
uint32_t u32;
u16 = htons(d.pf1);
memcpy(buffer+0, &u16, 2);
u32 = htonl(d.pf2>>32);
memcpy(buffer+2, &u32, 4);
u32 = htonl(d.pf2);
memcpy(buffer+6,&u32, 4);
}
void HeaderData(struct header h, struct data d, char buffer[18]) {
htonHeader(h, buffer+0);
htonData(d, buffer+8);
printf("buff is: %s\n",buffer);
}
#include <stdio.h>
#include "packet.c"
#include <string.h>
#include<stdlib.h>
int main(){
struct header h;
struct data d;
char buff[18];
//printf("Packet is: %s\n",buff);
printf("Generating Packets..... \n");
h.f1=1;
d.pf1=2;
h.f2=3;
d.pf2=4;
h.f3=5;
HeaderData(h,d,buff);
strcat(buff,buff+8);
printf("Packet is: %s\n",buff);
return 0;
}
The problem is that your printf()s are either syntactically wrong (printf( "%hu", ... ); expects an unsigned short as parameter, but you pass a pointer) or you try to print buff by using "%s" but the content is binary, not text. What you could do instead was doing some kind of hexdump, like:
int i;
for( i=0; i<sizeof( buff ); i++ ) {
printf( "%x ", buff[i] & 0xff );
}
puts( "" ); // terminate the line
Please note, that using sizeof works im main() only, in the other function you've got to determine the buffer size differently.
Besides: because of the binary content of buff, you can't use strcat(). Even if you have made sure that there is a '\0' behind the last value you have copied (I haven't checked if you have), depending on the integer values you copy, there may be another '\0' value before that one and strcat() would overwrite everything form that point on.
Related
I am writing a program which will read the file and save values in arrays.
this is my file:
communication1 : b8:27:eb:cf:54:2c, b8:27:eb:75:85:e4, 2000000;
communication2 : mm:27:eb:cf:54:2c, xx:27:eb:75:85:e4, 2200000;
This is my code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
struct mac{
uint8_t address_bytes [6];
};
void main(){
int count = 2, i = 0;
char *Trash[4], *Time[4];
int k=0;
int mac1[6], mac2[6];
char tempbuff[100];
char trash[20], mac_s[20], mac_d[20], time[20];
struct mac Mac1[2], Mac2[2];
int j = 0;
FILE *fptr = fopen("config", "r");
fseek(fptr, 0, SEEK_SET);
while(!feof(fptr)){
if (fgets(tempbuff,100,fptr)) {
printf("\n%s", tempbuff);
sscanf(tempbuff, "%15s : %17[^;], %17[^;], %17[^;];", trash, mac_s, mac_d, time);
Trash[i] = strdup(trash);
Time[i] = strdup(time);
sscanf(mac_s, "%x:%x:%x:%x:%x:%x", &mac1[0], &mac1[1], &mac1[2], &mac1[3], &mac1[4], &mac1[5]);
sscanf(mac_d, "%x:%x:%x:%x:%x:%x", &mac2[0], &mac2[1], &mac2[2], &mac2[3], &mac2[4], &mac2[5]);
for(j = 0; j < 6; j++){
Mac1[i].address_bytes[j] = (uint8_t) mac1[j];
Mac2[i].address_bytes[j] = (uint8_t) mac2[j];
}
printf ("Mac1[%d] is %02x:%02x:%02x:%02x:%02x:%02x and Time is %s\n", i, Mac1[i].address_bytes[0], Mac1[i].address_bytes[1], Mac1[i].address_bytes[2], Mac1[i].address_bytes[3],
Mac1[i].address_bytes[4], Mac1[i].address_bytes[5], Time[i]);
printf ("Mac2[%d] is %02x:%02x:%02x:%02x:%02x:%02x \n", i, Mac2[i].address_bytes[0], Mac2[i].address_bytes[1], Mac2[i].address_bytes[2], Mac2[i].address_bytes[3],
Mac2[i].address_bytes[4], Mac2[i].address_bytes[5]);
}
i++;
}
printf(" \n time0 is %s time1 is %s \n", Time[0], Time[1]);
fclose(fptr);
}
As you see, I am sscanf file and take 4 variables, than separately I sscanf mac addresses as pointers to type int and than trying to write them to a structure array. I have to achieve uint8_t values.
Output of this code is:
communication1 : b8:27:eb:cf:54:2c, b8:27:eb:75:85:e4, 2000000;
Mac1[0] is b8:27:eb:cf:54:2c and Time is 2000000
Mac2[0] is b8:27:eb:75:85:e4
communication2 : mm:27:eb:cf:54:2c, xx:27:eb:75:85:e4, 2200000;
Mac1[1] is b8:27:eb:cf:54:2c and Time is 2200000
Mac2[1] is b8:27:eb:75:85:e4
time0 is 2000000 time1 is 2200000
The problem is, that I can't find the way to duplicate pointers into uint8_t field of structure array. With strings I already got the hint - strdup, what about uint8_t?
To copy plain bytes like uint8_t, use memcpy:
int main() {
uint8_t s[6] = { 0x1, 0x2, 0x3,0x4,0x5,0x6 };
uint8_t *t;
t = malloc(6*sizeof(uint8_t));
memcpy(t,s,6*sizeof(uint8_t));
printf("%x %x %x %x %x %x\n", t[0],t[1],t[2],t[3],t[4],t[5]);
}
This my Mod bus crc_16 embedded code. I have run this code in code block many Times. There is no error but I am not getting actual crc value. I should get crc 05C8 and I am getting 8512 right now.
I think I giving wrong input while calling CRC method. I am passing string and its length. So please help me.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define POLY 0x8005
unsigned int ModRTU_CRC(unsigned char * mod_data,unsigned int length)
{
unsigned int CRC16 = 0xFFFF;
unsigned int pos=0,i=0;
for(pos=0;pos<length;pos++)
{
CRC16 ^= (unsigned int) mod_data[pos];
for(i=0;i<8;i++)
{
if((CRC16 & 0x0001)!=0)
{
CRC16 >>=1;
CRC16^=0xA001;
}
else
{
CRC16 >>=1;
}
}
}
return CRC16;
}
int main()
{
//char *frame = "010600081388";
// char *frame = "010300080001";
char frame[7];
frame[0]=0x01;
frame[1]=0x03;
frame[2]=0x00;
frame[3]=0x08;
frame[4]=0x00;
frame[5]=0x01;
frame[6]='\0';
printf("%x\n",frame);
int len = strlen(frame);
unsigned int crcv = ModRTU_CRC(frame,len);
printf("%x\n",crcv);
return 0;
}
The bug is that in your original code you used frame[2]=0x00; followed by strlen(), which will interpret this as the null terminator and give the wrong size 2 instead of 6. You cannot use strlen() on binary data.
In the "fixed" version you hard-code the size to 6 so the bug was removed by accident. It has nothing to do with uint8_t versus char (although it is always better to use uint8_t for binary data).
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define POLY 0x8005
unsigned int ModRTU_CRC(unsigned char * mod_data,unsigned int length)
{
unsigned int CRC16 = 0xFFFF;
unsigned int pos=0,i=0;
for(pos=0;pos<length;pos++)
{
CRC16 ^= (unsigned int) mod_data[pos];
for(i=0;i<8;i++)
{
if((CRC16 & 0x0001)!=0)
{
CRC16 >>=1;
CRC16^=0xA001;
}
else
{
CRC16 >>=1;
}
}
}
return CRC16;
}
int main()
{
uint8_t message[80] = { // 6-byte test vector
0x01, 0x03, 0x00, 0x08, 0x00, 0x01
};
int message_length = 6;
printf("%x\n",message);
// int len = strlen(message);
uint16_t the_CRC = ModRTU_CRC(message,message_length);
printf("%x\n",the_CRC);
return 0;
}
`
I want to basically process a struct array in a method in a dynamic library, but when I pass the array and print it (in the exact same manner as in my main program) it has different values.
Consider a struct like this:
struct color {
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
}
And the code to print it looks like this:
printf("pos: %p\n", array);
for (i = 0; i < size; i++) {
printf("bgra: %08x\n", ((uint32_t *) array)[i]);
}
Now, what I'm doing in the test program is this:
printf("Table:\n");
print(table, size);
and the output looks like this (as excepted):
pos: 0x7fff5b359530
bgra: 00000000
bgra: ff0000ff
bgra: ff00ffff
But when i execute the same code in a function in the library this is what i get:
pos: 0x7fff5b359530
bgra: 00000008
bgra: 00000030
bgra: 5b3598e0
Now I'm wondering what I'm doing wrong, since i can't see a fault in my code. Also, the values must correlate somehow since, the output is always the same (Except for the address of course).
header.h
#include <stdint.h>
#ifndef __HEADER_H_
#define __HEADER_H_
struct bmpt_color_bgra {
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
};
void print(struct bmpt_color_bgra *table, uint8_t size);
uint8_t *gen(struct bmpt_color_bgra *table, uint8_t size);
#endif
library.c
#include <stdlib.h>
#include <stdio.h>
#include "header.h"
#define EXPORT __attribute__((visibility("default")))
__attribute__((constructor))
static void initializer(void) {
printf("[%s] initializer()\n", __FILE__);
}
__attribute__((destructor))
static void finalizer(void) {
printf("[%s] finalizer()\n", __FILE__);
}
EXPORT
void print(struct bmpt_color_bgra *table, uint8_t size) {
uint8_t i;
printf("pos: %p\n", table);
for (i = 0; i < size; i++) {
printf("bgra: %08x\n", ((uint32_t *) table)[i]);
}
}
EXPORT
uint8_t *gen(struct bmpt_color_bgra *table, uint8_t size) {
printf("table in func:\n");
print(table, size);
}
test.c
#include <stdio.h>
#include <stdlib.h>
#include "header.h"
int main(int argc, char **argv) {
struct bmpt_color_bgra arr[3];
struct bmpt_color_bgra c;
c.b = 0x0;
c.g = 0x0;
c.r = 0x0;
c.a = 0x0;
arr[0] = c;
c.b = 0xff;
c.a = 0xff;
arr[1] = c;
c.r = 0xff;
arr[2] = c;
//the first result (the correct one)
print(arr, 3);
//the second result
gen(arr, 3);
}
This probably comes down to memory alignment of the members within the struct, and the size of the struct itself differing between your program and the dynamic/shared library. You don't mention which compiler you are using, but using different compiler(s) or compiler options for your program and the shared library could cause this effect.
You can preserve binary compatibility between modules by specifying exactly how the members of the struct should be aligned. E.g in GCC you can force how the struct is represented in memory by use of an attribute.
See https://gcc.gnu.org/onlinedocs/gcc-3.3/gcc/Type-Attributes.html for GCC alignment instructions
struct bmpt_color_bgra {
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
} __attribute__ ((packed));
Also take a look at Byte Alignment for integer (or other) types in a uint8_t array for a similar question.
I'm designing a binary file format to store strings[without terminating null to save space] and binary data.
i. What is the best way to deal with little/big endian systems?
i.a Would converting everything to network byte order and back with ntohl()/htonl() work?
ii. Will the packed structures be the same size on x86, x64 and arm?
iii. Are their any inherent weakness with this approach?
struct __attribute__((packed)) Header {
uint8_t magic;
uint8_t flags;
};
struct __attribute__((packed)) Record {
uint64_t length;
uint32_t crc;
uint16_t year;
uint8_t day;
uint8_t month;
uint8_t hour;
uint8_t minute;
uint8_t second;
uint8_t type;
};
Tester code I'm using the develop the format:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <limits.h>
#include <strings.h>
#include <stdint.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
struct __attribute__((packed)) Header {
uint8_t magic;
uint8_t flags;
};
struct __attribute__((packed)) Record {
uint64_t length;
uint32_t crc;
uint16_t year;
uint8_t day;
uint8_t month;
uint8_t hour;
uint8_t minute;
uint8_t second;
uint8_t type;
};
int main(void)
{
int fd = open("test.dat", O_RDWR|O_APPEND|O_CREAT, 444);
struct Header header = {1, 0};
write(fd, &header, sizeof(header));
char msg[] = {"BINARY"};
struct Record record = {strlen(msg), 0, 0, 0, 0, 0, 0, 0};
write(fd, &record, sizeof(record));
write(fd, msg, record.length);
close(fd);
fd = open("test.dat", O_RDWR|O_APPEND|O_CREAT, 444);
read(fd, &header, sizeof(struct Header));
read(fd, &record, sizeof(struct Record));
int len = record.length;
char c;
while (len != 0) {
read(fd, &c, 1);
len--;
printf("%c", c);
}
close(fd);
}
i. Defining the file to be in one order and converting to and from "internal" order, if necessary, when reading/writing (perhaps with ntohl and the like) is, in my opinion, the best approach.
ii. I do not trust packed structures. They might work for this approach for those platforms, but there are no guarantees.
iii. Reading and writing binary files using fread and fwrite on whole structs is (again in my opinion) an inherently weak approach. You maximize the likelihood that you will be bitten by word size problems, padding and alignment problems, and byte order problems.
What I like to do is write little functions like get16() and put32() that read and write a byte at a time and so are inherently insensitive to word size and byte order difficulties. Then I write straightforward putHeader and getRecord functions (and the like) in terms of these.
unsigned int get16(FILE *fp)
{
unsigned int r;
r = getc(fp);
r = (r << 8) | getc(fp);
return r;
}
void put32(unsigned long int x, FILE *fp)
{
putc((int)((x >> 24) & 0xff), fp);
putc((int)((x >> 16) & 0xff), fp);
putc((int)((x >> 8) & 0xff), fp);
putc((int)(x & 0xff), fp);
}
[P.S. As #Olaf correctly points out in one of the comments, in production code you'd need handling for EOF and error in these functions. I've left those out for simplicity of presentation.]
I have a code which looks as shown below. The code here is if the word_size = 64. In similar fashion I need to have for 32 and 16 too. I can't find a way to reuse the same encrypt function for all the sizes. Moreover, I need to declare the variables too according to the word_size, ie. to use either uint_16 or uint_32 or uint_64 depends upon word_size. Can you help me with writing a reusable code in this case?
#include<stdio.h>
#include<stdint.h>
void encrypt(uint64_t* , uint64_t*, uint64_t*);
int main(){
int block_size;
// Get the user inputs
printf("input the block size: \n");
scanf("%d", &block_size); // can be 32, 64 or 128
int word_size = block_size/2; // 16,32 or 64
// Depending on the word_size, I should declare the variables with
// corresponding width
uint64_t plain_text[2] = {0,0};
uint64_t cipher_text[2] = {0,0};
uint64_t key_text[2] = {0,0};
uint64_t * pt, *ct, *k;
encrypt(pt, ct,k);
}
/*
* Ecnryption Method
*/
void encrypt(uint64_t* pt, uint64_t* ct, uint64_t* k){
// Involves bit shifting algorithm which works only on exact sizes i.e eiter 16,32 or 64.
}
I can provide more information if needed.
There is a way to do this in C - by using struct and union
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
enum type {
U64,
U32,
U16,
U8,
};
struct container {
enum type type;
union {
uint64_t u64;
uint32_t u32;
uint16_t u16;
uint8_t u8;
} value;
};
int test(struct container container) {
switch(container.type) {
case U64:
printf("Value is :%" PRIu64 "\n", container.value);
break;
case U32:
printf("Value is :%" PRIu32 "\n", container.value);
break;
case U16:
printf("Value is :%" PRIu16 "\n", container.value);
break;
case U8:
printf("Value is :%" PRIu8 "\n", container.value);
break;
}
return 0;
}
int main(int argc, char **argv) {
struct container c1, c2;
c1.type = U64;
c1.value.u64 = 10000000000ULL;
c2.type = U8;
c2.value.u8 = 100;
test(c1);
test(c2);
return 0;
}
The output produced was:
Value is :10000000000
Value is :100