issue with C pwrite(); extra bytes got written to file - c

I am having a weird issue when i do a pwrite a struct to a file. It adds a single byte with next to a char entry in the struct. When i tried to write the char alone to a file it correctly wrote a single byte. Could some one tell me why the single byte got added??
int main(){
typedef struct pcap_hdr_s {
guint32 magic_number; /* magic number */
guint16 version_major; /* major version number */
guint16 version_minor; /* minor version number */
gint32 thiszone; /* GMT to local correction */
guint32 sigfigs; /* accuracy of timestamps */
guint32 snaplen; /* max length of captured packets, in octets */
guint32 network; /* data link type */
guint32 ts_sec; /* timestamp seconds */
guint32 ts_usec; /* timestamp microseconds */
guint32 incl_len; /* number of octets of packet saved in file */
guint32 orig_len; /* actual length of packet */
guint16 fcf;
char seqno;
guint16 dpan;
guint16 daddr;
guint16 saddr;
gint16 payload_data;
} pcaprec_hdr_t;
pcaprec_hdr_t packet_header;
packet_header.magic_number = PCAP_MAGIC;
packet_header.version_major = 2;
packet_header.version_minor = 4;
packet_header.thiszone = 0;
packet_header.sigfigs = 0;
packet_header.snaplen = 65535;
packet_header.network = 195;
struct timeval tv;
gettimeofday(&tv, NULL);
packet_header.ts_sec = tv.tv_sec;
packet_header.ts_usec = tv.tv_usec;
packet_header.incl_len = 11;
packet_header.orig_len = 13;
packet_header.seqno = 255;
packet_header.dpan = 65535;
packet_header.daddr = 65535;
packet_header.saddr = 65535;
packet_header.payload_data = 8;
int fd = open("sample.cap", O_CREAT | O_WRONLY);
printf("Bytes written: %d \n",pwrite(fd, &packet_header, sizeof(packet_header),0));
}
The struct has a char var "seq" and next to the seq no value a single byte of random value gets added in the file.

Your structure contains a char data member and you probably have word-alignment on. See if you can find a "pack" option in the compiler.
You can probably use a #pragma pack(1) or similar pragma (pragma's are implementation specific) to change the alignment for a particular set of classes.
Be careful though, the compiler word-aligns for performance reasons. The memory bus typically works on word boundaries, so you could end up requiring two fetchs for each word that straddles the word boundary thereby slowing memory access down a bit.
You might want to stream the structure members out individually if you're concerned about the added bytes in the file.

Related

Cannot run a large structure filled with arrays win C

I'm building a SAE J1939 library for embedded systems such as Arduino, STM32, AVR etc.
But I have an issue I don't understand. First when I compile. No error!
But when I run, I get this assembler error. It's all about the J1939 struct.
Why does this happen? Is the heap to small?
Can't find a source file at
"C:\mingw810\i686-810-posix-dwarf-rt_v6-rev0\build\gcc-8.1.0\i686-w64-mingw32\libgcc/../../../../../src/gcc-8.1.0/libgcc/config/i386/cygwin.S"
Locate the file or edit the source lookup path to include its
location.
Run this code below to reproduce the error:
#include <stdio.h>
#include <stdlib.h>
#include "stdint.h"
/* PGN: 0x00E800 - Storing the Acknowledgement from the reading process */
struct Acknowledgement {
uint8_t control_byte; /* This indicates the status of the requested information about PGN: */
uint8_t group_function_value; /* The function code that specify cause of the control byte e.g time out or aborted */
uint8_t address; /* Address from the ECU where the acknowledgement is comming from */
uint32_t PGN_of_requested_info; /* Information request about the PGN */
};
/* PGN: 0x00EC00 - Storing the Transport Protocol Connection Management from the reading process */
struct TP_CM {
uint8_t control_byte; /* What type of message are we going to send */
uint16_t total_message_size; /* Total bytes our complete message includes */
uint8_t number_of_packages; /* How many times we are going to send packages via TP_DT */
uint32_t PGN_of_the_packeted_message; /* Our message is going to activate a PGN */
};
/* PGN: 0x00EB00 - Storing the Transport Protocol Data Transfer from the reading process */
struct TP_DT {
uint8_t sequence_number; /* When this sequence number is the same as number_of_packages from TP_CM, then we have our complete message */
uint8_t data[7][256]; /* Package data of 2D array where first index is data0 -> data6 and second index is sequence of the data */
};
/* PGN: 0x00EE00 - Storing the Address claimed from the reading process */
struct Name {
uint32_t identity_number; /* Specify the ECU serial ID - 0 to 2097151 */
uint16_t manufacturer_code; /* Specify the ECU manufacturer code - 0 to 2047 */
uint8_t function_instance; /* Specify the ECU function number - 0 to 31 */
uint8_t ECU_instance; /* Specify the ECU number - 0 to 7 */
uint8_t function; /* Specify the ECU function - 0 to 255 */
uint8_t vehicle_system; /* Specify the type of vehicle where ECU is located - 0 to 127 */
uint8_t arbitrary_address_capable; /* Specify if the ECU have right to change address if addresses conflicts - 0 to 1 */
uint8_t industry_group; /* Specify the group where this ECU is located - 0 to 7 */
uint8_t vehicle_system_instance; /* Specify the vehicle system number - 0 to 15 */
};
/* PGN: 0x00FECA - Storing the DM1 Active diagnostic trouble codes from the reading process */
struct DM1 {
/* These are SAE lamps can have 1 = ON and 0 = OFF */
uint8_t SAE_lamp_status_malfunction_indicator;
uint8_t SAE_lamp_status_red_stop;
uint8_t SAE_lamp_status_amber_warning;
uint8_t SAE_lamp_status_protect_lamp;
uint8_t SAE_flash_lamp_malfunction_indicator;
uint8_t SAE_flash_lamp_red_stop;
uint8_t SAE_flash_lamp_amber_warning;
uint8_t SAE_flash_lamp_protect_lamp;
/* Fault location, problem and codes */
uint32_t SPN; /* Location where the fault exist */
uint8_t FMI; /* Type of problem */
uint8_t SPN_conversion_method; /* If SPN_conversion_method = 1 that means Diagnostics Trouble Code are aligned using a newer conversion method. If SPN_conversion_method = 0 means one of the three Diagnostics Trouble Code conversion methods is used and ECU manufacture shall know which of the three methods is used */
uint8_t occurence_count; /* This tells how many times failure has occurred. Every time fault goes from inactive to active, the occurence_count is incremented by 1. If fault becomes active for more than 126 times the occurence_count remains 126 */
};
/* PGN: 0x00D800 - Storing the DM15 response from the reading process */
struct DM15 {
uint16_t number_of_allowed_bytes; /* How many bytes we are allowed to write or read to */
uint8_t status; /* Status of the response */
uint32_t EDC_parameter; /* Status code */
uint8_t EDCP_extention; /* Describe how we should interpret the EDC parameter as a status code or error code */
uint16_t seed; /* Response of the key if we need more key or no key at all */
};
/* PGN: 0x00D700 - Storing the DM16 binary data transfer from the reading process */
struct DM16 {
uint8_t number_of_occurences; /* How many bytes we have sent */
uint8_t raw_binary_data[256]; /* Here we store the bytes */
};
/* Storing the error codes from the reading process */
struct DM {
uint8_t errors_dm1_active; /* How many errors of DM1 we have right now */
uint8_t errors_dm2_active; /* How many errors of DM2 is active */
struct DM1 dm1[256]; /* dm1 can contains multiple error messages */
struct DM1 dm2[256]; /* dm2 contains previously active errors from dm1 */
struct DM15 dm15; /* dm15 is the memory access response from DM14 memory request */
struct DM16 dm16; /* dm16 is the binary data transfer after DM15 memory response (if it was proceeded) */
/* Add more DM here */
};
/* PGN: 0x00FEDA - Storing the software identification from the reading process */
struct Software_identification {
uint8_t length_of_each_identification; /* The length of each identification - Not part of J1939 standard */
uint8_t number_of_fields; /* How many numbers contains in the identifications array */
uint8_t identifications[256]; /* This can be for example ASCII */
};
/* PGN: 0x00FDC5 - Storing the ECU identification from the reading process */
struct ECU_identification {
uint8_t length_of_each_field; /* The real length of the fields - Not part of J1939 standard */
uint8_t ecu_part_number[256]; /* ASCII field */
uint8_t ecu_serial_number[256]; /* ASCII field */
uint8_t ecu_location[256]; /* ASCII field */
uint8_t ecu_type[256]; /* ASCII field */
uint8_t ecu_manufacturer[256]; /* ASCII field */
uint8_t ecu_hardware_version[256]; /* ASCII field */
};
/* PGN: 0x00FEEB - Storing the component identification from the reading process */
struct Component_identification {
uint8_t length_of_each_field; /* The real length of the fields - Not part of J1939 standard */
uint8_t component_product_date[256]; /* ASCII field */
uint8_t component_model_name[256]; /* ASCII field */
uint8_t component_serial_number[256]; /* ASCII field */
uint8_t component_unit_name[256]; /* ASCII field */
};
/* PGN: 0x00FE30 (65072) to 0x00FE3F (65087) */
struct Auxiliary_valve_command {
uint8_t standard_flow; /* Command flow */
uint8_t fail_safe_mode; /* If the user want the valve to go to neutral */
uint8_t valve_state; /* Retract, Extend, Neutral, Init, Error etc */
};
/* PGN: 0x00FE10 (65040) to 0x00FE1F (65055) */
struct Auxiliary_valve_estimated_flow {
uint8_t extend_estimated_flow_standard; /* A measurement */
uint8_t retract_estimated_flow_standard; /* A measurement */
uint8_t valve_state; /* Retract, Extend, Neutral, Init, Error etc */
uint8_t fail_safe_mode; /* The mode if we are going to use fail safe mode or not */
uint8_t limit; /* Enter a limit code */
};
/* PGN: 0x00C400 (50176) */
struct General_purpose_valve_command {
uint8_t standard_flow; /* Command flow */
uint8_t fail_safe_mode; /* If the user want the valve to go to neutral */
uint8_t valve_state; /* Retract, Extend, Neutral, Init, Error etc */
uint16_t extended_flow; /* Another command flow */
};
/* PGN: 0x00C600 (50688) */
struct General_purpose_valve_estimated_flow {
uint8_t extend_estimated_flow_standard; /* A measurement */
uint8_t retract_estimated_flow_standard; /* A measurement */
uint8_t valve_state; /* Retract, Extend, Neutral, Init, Error etc */
uint8_t fail_safe_mode; /* The mode if we are going to use fail safe mode or not */
uint8_t limit; /* Enter a limit code */
uint16_t extend_estimated_flow_extended; /* A measurement */
uint16_t retract_estimated_flow_extended; /* A measurement */
};
struct Auxiliary_valve_measured_position {
uint16_t measured_position_procent; /* Procent position */
uint8_t valve_state; /* Retract, Extend, Neutral, Init, Error etc */
uint16_t measured_position_micrometer; /* Micrometer position */
};
typedef struct {
/* For information about other ECU */
uint8_t number_of_ECU;
uint8_t number_of_cannot_claim_address;
uint8_t ECU_address[256];
struct Acknowledgement acknowledgement[256];
struct TP_CM tp_cm[256];
struct TP_DT tp_dt[256];
struct Name name[256];
struct DM dm[256];
struct Software_identification software_identification[256];
struct ECU_identification ecu_identification[256];
struct Component_identification component_identification[256];
struct Auxiliary_valve_estimated_flow auxiliary_valve_estimated_flow[256][16];
struct General_purpose_valve_estimated_flow general_purpose_valve_estimated_flow[256];
struct Auxiliary_valve_measured_position auxiliary_valve_measured_position[256][16];
/* For information about this ECU */
struct Name this_name;
uint8_t this_ECU_address;
struct DM this_dm;
struct Software_identification this_software_identification;
struct ECU_identification this_ecu_identification;
struct Component_identification this_component_identification;
struct Auxiliary_valve_command this_auxiliary_valve_command[16];
struct General_purpose_valve_command this_general_purpose_valve_command;
} J1939;
int main(void) {
J1939 j1939;
puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */
return EXIT_SUCCESS;
}
This information is not a compilation error. You execute a debugger and try to debug a part of program without located sources. This could happen if your program stops in a compiled library. Then we can use a assembler instruction only. As mentioned above try to set breakpoint into your main() funcion.

Get USB Host Controller parameters in Linux programmatically

I need to get some parameters related to USB Host Controllers in Linux. I made a lot of searches in the internet and the only way that I found is using pciutils lib. Each PCI device is in the structure pci_dev in pci.h:
struct pci_dev {
struct pci_dev *next; /* Next device in the chain */
u16 domain_16; /* 16-bit version of the PCI domain for backward compatibility */
/* 0xffff if the real domain doesn't fit in 16 bits */
u8 bus, dev, func; /* Bus inside domain, device and function */
/* These fields are set by pci_fill_info() */
int known_fields; /* Set of info fields already known */
u16 vendor_id, device_id; /* Identity of the device */
u16 device_class; /* PCI device class */
int irq; /* IRQ number */
pciaddr_t base_addr[6]; /* Base addresses including flags in lower bits */
pciaddr_t size[6]; /* Region sizes */
pciaddr_t rom_base_addr; /* Expansion ROM base address */
pciaddr_t rom_size; /* Expansion ROM size */
struct pci_cap *first_cap; /* List of capabilities */
char *phy_slot; /* Physical slot */
char *module_alias; /* Linux kernel module alias */
char *label; /* Device name as exported by BIOS */
int numa_node; /* NUMA node */
pciaddr_t flags[6]; /* PCI_IORESOURCE_* flags for regions */
pciaddr_t rom_flags; /* PCI_IORESOURCE_* flags for expansion ROM */
int domain; /* PCI domain (host bridge) */
/* Fields used internally */
struct pci_access *access;
struct pci_methods *methods;
u8 *cache; /* Cached config registers */
int cache_len;
int hdrtype; /* Cached low 7 bits of header type, -1 if unknown */
void *aux; /* Auxiliary data */
struct pci_property *properties; /* A linked list of extra properties */
struct pci_cap *last_cap; /* Last capability in the list */
};
I found also that I can parse pci devices as following:
struct pci_access *pacc1;
struct pci_dev *dev1;
unsigned int c1;
char namebuf1[1024], *name1;
pacc1 = pci_alloc(); /* Get the pci_access structure */
/* Set all options you want -- here we stick with the defaults */
pci_init(pacc1); /* Initialize the PCI library */
pci_scan_bus(pacc1); /* We want to get the list of devices */
for (dev1=pacc1->devices; dev1; dev1=dev1->next) /* Iterate over all devices */
{
pci_fill_info(dev1, PCI_FILL_IDENT | PCI_FILL_BASES | PCI_FILL_CLASS); /* Fill in header info we need */
c1 = pci_read_byte(dev1, PCI_INTERRUPT_PIN); /* Read config register directly */
printf("%04x:%02x:%02x.%d vendor=%04x device=%04x class=%04x irq=%d (pin %d) base0=%lx",
dev1->domain, dev1->bus, dev1->dev, dev1->func, dev1->vendor_id, dev1->device_id,
dev1->device_class, dev1->irq, c1, (long) dev1->base_addr[0]);
/* Look up and print the full name of the device */
name1 = pci_lookup_name(pacc, namebuf1, sizeof(namebuf1), PCI_LOOKUP_DEVICE, dev1->vendor_id, dev1->device_id);
printf(" ***************** %d: (%s)\n", dev1->dev, name1);
}
pci_cleanup(pacc1); /* Close everything */
Is there a way to check in the loop if the corresponding pci device corresponds to an USB Host Controller? Or is there a simpler way to get USB Host Controller infos?

TCP Checksum in C [duplicate]

This question already has answers here:
C Programming TCP Checksum
(4 answers)
Closed 5 years ago.
I've been trying to calculate the checksum of a TCP header in C. For my purposes, the TCP header is 20 bytes long and has no extra data or options. Also, according to my knowledge, the TCP checksum is calculated as the one's complement of the one's complement sum of the 16 bit words in the header. So, I wrote a function to calculate the TCP checksum, considering the conditions I stated above. However, when I examine the packet being sent out after I calculate the checksum, I get this:
1 0.000000 10.0.2.15 -> 127.0.0.1 TCP 74 24131->8000 [SYN] Seq=0 Win=13273 [TCP CHECKSUM INCORRECT] Len=20
I examined the packet using tshark. However, I also examined the packets with Wireshark, and it also said the same thing. Except, that in parenthesis, it said, "maybe caused by TCP checksum offload?" Which, I don't fully understand.
Here's the code I used to calculate the checksum:
unsigned short tcp_checksum(struct tcphdr* tcph,struct iphdr* iph) {
/* Calculate TCP checksum */
struct pseudo_hdr* pseudo_hdr;
u_char* buffer;
u_char* segment;
u_char* pseudo_segment;
unsigned int count = 32;
unsigned long sum = 0;
unsigned short mask = 0xffff;
unsigned long long* hdr;
pseudo_hdr = malloc(sizeof(struct pseudo_hdr)); // allocate memory
buffer = malloc(32); // allocate for 32 bytes of information
if (pseudo_hdr == NULL || buffer == NULL) { // if memory wasn't allocated properly
err();
if (pseudo_hdr != NULL) free(pseudo_hdr);
if (buffer != NULL) free(buffer);
return 0;
}
pseudo_hdr->saddr = (unsigned long)iph->saddr; // we add the cast because the fields if of type u_int_32
pseudo_hdr->daddr = (unsigned long)iph->daddr; // same reason for adding the cast as above
bzero(&pseudo_hdr->reserved,sizeof(pseudo_hdr->reserved)); // zero header
pseudo_hdr->proto = IPPROTO_TCP; // this will always be 6
pseudo_hdr->len = htons(tcph->doff*4); // length of tcp header
/* Place both headers into a buffer */
segment = (u_char*)tcph;
pseudo_segment = (u_char*)pseudo_hdr;
/* Concactenate */
memcpy((char*)buffer,(char*)pseudo_segment,sizeof(struct pseudo_hdr)); // first the pseudo header
memcpy((char*)buffer+12,(char*)segment,sizeof(struct tcphdr)); // then the TCP segment
/* Calculate checksum just like IP checksum (RFC C implementation) */
hdr = (unsigned long long*)buffer;
while (count > 1) {
sum += *(unsigned short*)hdr++;
count -= 2;
}
// Add left over bytes, if any
if (count > 0) sum += * (u_char*) hdr;
// Fold 32-bit sum to 16 bits
while (sum>>16) sum = (sum & mask) + (sum >> 16);
sum = ~sum; // bitwise NOT operation
/* Discard headers and buffer */
free(buffer);
free(pseudo_hdr);
return sum;
}
struct iphdr and struct tcphdr are defined in <netinet/ip.h> and <netinet/tcp.h>. Here's my definition of struct pseudo_hdr:
struct pseudo_hdr {
unsigned long saddr; // 4 bytes
unsigned long daddr; // 4 bytes
unsigned char reserved; // 1 byte
unsigned char proto; // 1 byte
unsigned short len; // 2 bytes
};
/* Total = 4+4+1+1+2 = 12 bytes */
As I said, this function, for my purposes, calculates the checksum for a TCP header that is 20 bytes long.
Thank you for any help or recommendations.
#RonMaupin's suggestions about checking out the RFC's and the contribution of everyone else to further my understanding of TCP (and C in general!) helped me to solve my problem. Thank you!

error: dereferencing pointer to incomplete type when accessing struct

I am not sure why this is happening. I am doing an assignment and the code somehow does not compile.
This is the header file
#include <stdint.h>
typedef struct
{
uint8_t jump_code[3]; /* Ignore this */
char oemname[8]; /* Might as well ignore this one too */
uint8_t ssize[2]; /* Sector size in bytes */
uint8_t csize; /* Cluster size in sectors */
uint8_t reserved[2]; /* Number of reserved sectors for boot sectors */
uint8_t numfat; /* Number of FATs */
uint8_t numroot[2]; /* Number of Root directory entries */
uint8_t sectors16[2]; /* number of sectors in the file system */
uint8_t media[1]; /* Media descriptor type */
uint8_t sectperfat16[2];/* Number of sectors per FAT */
uint8_t sectpertrack[2];/* Number of sectors per track */
uint8_t heads[2]; /* Number of heads */
uint8_t prevsect[2]; /* Number of sectors before FS partition */
uint8_t ignore[482]; /* Ignore these */
} boot_sect_t;
This is the part that gives the error:
struct boot_sect_t* boot = malloc(sizeof(boot_sect_t));
boot->ssize[0] = buffer[11]; //error here
boot->ssize[1] = buffer[12]; //error here
The error is:
error: dereferencing pointer to incomplete type when accessing struct
you need to change
struct boot_sect_t* boot = malloc(sizeof(boot_sect_t));
to
boot_sect_t* boot = malloc(sizeof(boot_sect_t));
boot_sect_t is already a typedef. no need to write struct boot_sect_t.

Error in packet parsing

i trying to parse a packet. till the ip header everything is fine(i'm able to retrieve all the values correctly). but for the udp header( checked if the protocol is 17) , the values are coming out to be wrong( all the 4 fields).
I'm trying to do this:
struct udp_header{
uint16_t sport;
uint16_t dport;
uint16_t len;
uint16_t chksum;
};
struct udp_header* udp= (struct udp_header*)(packet + 14 + ip_hdr->ip_hl*4);
Packet is the pointer pointing to the beginning of the packet. 14 is for ethernet header.The header length ip when checked is giving out the correct value. But after performing this operation i'm getting all the fields wrongly. when tried with uint8_t as data type( i know its wrong! ) the destintion port somehow is coming out correct.
You have run into endianness. IP packets have all fields in network byte order (aka "big-endian"), and your host system probably runs little-endian. Look into ntohs() and friends for one approach.
The proper approach is to not copy the structure as-is from the network data, but instead extract each field manually and byte-swap it if necessary. This also works around any issues with padding and alignment, there's no guarantee that your struct is mapped into your computer's memory in exactly the same way as the packet is serialized.
So you would do e.g.:
udp_header.sport = ntohs(*(unsigned short*) (packet + 14 + 4 * ip_hdr->ip_hl));
This is also a bit iffy, since it assumes the resulting address can validly be cast into a pointer to unsigned short. On x86 that will work, but it's not epic.
Even better, in my opinion, is to drop the use of pointers and instead write a function called e.g. unsigned short read_u16(void *packet, size_t offset) that extracts the value byte-by-byte and returns it. Then you'd just do:
udp_header.sport = read_u16(packet, 14 + 4 * ip_hdr->ip_hl);
I always use this struct for IP header:
struct sniff_ip {
u_char ip_vhl; /* version << 4 | header length >> 2 */
u_char ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
#define IP_RF 0x8000 /* reserved fragment flag */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
u_char ip_ttl; /* time to live */
u_char ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src,ip_dst; /* source and dest address */
};
#define IP_HL(ip) (((ip)->ip_vhl) & 0x0f)
#define IP_V(ip) (((ip)->ip_vhl) >> 4)
And to get the UDP struct pointer:
udp = (struct sniff_udp*)(packet + SIZE_ETHERNET + (IP_HL(ip)*4));
As another answer remarked, you have to deal with endianness of your data.
The other thing you need to deal with is byte alignment. For speed, when you define a structure in C like this:
struct udp_header{
uint16_t sport;
uint16_t dport;
uint16_t len;
uint16_t chksum;
};
The C compiler may leave padding bytes between these fields so that member accesses can be done with faster single-instruction memory access assembly instructions. You can check if your c compiler is doing this by printf("struct size is: %u\n", sizeof(struct udp_header));
Assuming you are using GCC, you must disable padding bytes by adding #pragma pack(1) before the structure definition. To re-enable padding for speed you should then use #pragma pack().

Resources