I want to create a DNS response to send to my browser. I've created some structs like in the rfc:
//DNS header
struct DNS_HEADER
{
unsigned short id;
unsigned char rd :1;
unsigned char tc :1;
unsigned char aa :1;
unsigned char opcode :4;
unsigned char qr :1;
unsigned char rcode :4;
unsigned char cd :1;
unsigned char ad :1;
unsigned char z :1;
unsigned char ra :1;
unsigned short q_count;
unsigned short ans_count;
unsigned short auth_count;
unsigned short add_count;
};
#pragma pack(push, 1)
struct R_DATA
{
unsigned short type;
unsigned short _class;
unsigned int ttl;
unsigned short data_len;
};
#pragma pack(pop)
struct RES_RECORD
{
unsigned char *name;
struct R_DATA *resource;
unsigned char *rdata;
};
Now I'm trying to fill in this structs so I could send a valid DNS response. I'm trying to send for example www.google.com with ipaddres 112.12.12.12 (just for fun).
This is what I have:
dns = (DNS_HEADER*)malloc(sizeof(DNS_HEADER));
dns->id = (unsigned short) htons(GetCurrentProcessId()); // ID
dns->qr = 1; // We give a response, Volgens RFC: (= query (0), or a response (1).)
dns->opcode = 0; // default
dns->aa = 0; //Not Authoritative,RFC: (= Authoritative Answer - this bit is valid in responses, and specifies that the responding name server is an authority for the domain name in question section.)
dns->tc = 0; // Not truncated
dns->rd = 1; // Enable recursion
dns->ra = 0; // Nameserver supports recursion?
dns->z = 0; // RFC: (= Reserved for future use. Must be zero in all queries and responses.)
dns->rcode = 0; // No error condition
dns->q_count = 0; // No questions!
dns->ad = 0; // How man resource records?
dns->cd = 0; // !checking
dns->ans_count = 1; // We give 1 answer
dns->auth_count = 0; // How many authority entries?
dns->add_count = 0; // How many resource entries?
But as you can see I'm have some questions about what to fill in.
Also the R_Data and res_record I can't find out via the rfc what to fill in for a random response I've made...
Can someone help me with this?
Your approach is fundamentally flawed. You cannot express a DNS packet with a struct, because the strings in a DNS packet are variable length, i.e. fields following a string will be at different offsets in the packet depending on the length of the preceding strings.
Your struct has char-pointers in place of each string, and each pointer is typically a 32-bit value that points to some other place in memory. Therefore when you try to send the struct as represented in memory, you will be sending more or less random 32-bit values in place of the strings.
Here is a fairly illustrative guide to what the DNS packets should look like: http://www.tcpipguide.com/free/t_DNSMessageProcessingandGeneralMessageFormat.htm
A few pointers at a glance: id in your response needs to be the id you received in the query. q_count should be 1 and repeat the query you received (in your example that'd be e.g. \x03www\x06google\x03com\x00\x00\x01\x00\x01 for www.google.com IN A). What needs to go in rdata is explained in RFC1035 Section 3.4.1 (in your example it'd be \x70\x0c\x0c\x0c).
Related
I have a bit-field structure "struct errors" of size 1 byte and I am using its data using a mask "ERR_MASK" as shown in below code.
My requirement is that if the type of the structure is changed, the mask need to be adapted accordingly.
Since I am importing this structure type from another component or module (file1.h in below code),
I want to define a copy of this structure type "struct copy_errors" in my source file (file2.c in below code) and check if it has got changed with original type in file1.h,
If there is a mismatch, I want to throw an compilation error from file2.c. Can anyone tell me how do I achieve this? Or is there any other way to do this?
Note: I don't want to access "struct errors" with its elements.
/*file1.h*/
struct errors
{
unsigned char err0 :1;
unsigned char err1 :1;
unsigned char err2 :1;
unsigned char err3 :1;
unsigned char err4 :1;
unsigned char err5 :1;
unsigned char reserved1 :1;
unsigned char reserved2 :1;
};
/*file2.c*/
#include "file1.h"
#define ERR_MASK 0xFCU
struct copy_errors
{
unsigned char err0 :1;
unsigned char err1 :1;
unsigned char err2 :1;
unsigned char err3 :1;
unsigned char err4 :1;
unsigned char err5 :1;
unsigned char reserved1 :1;
unsigned char reserved2 :1;
};
bool function(struct err*)
{
bool ret=0;
unsigned char * err_ptr;
err_ptr = (unsigned char *) err;
if (((*err_ptr) & ERR_MASK) != 0U)
{
ret = 1;
}
return ret;
}
C doesn't support anything equivalent. If you have a tool chain that supports custom build events, you could introduce a pre-build step calling e. g. a python script (or any other language you prefer). This script then would:
load the header file
iterate over all lines until it finds the structure in question
check for all known members in desired order (i. e. no members replaced)
finally check, if end of structure is reached (i. e. no new members added)
If your tool chain stops, if the pre-build task fails, you are out already (just return 0 on success and anything else on failure), otherwise you could create a simple C-File, empty on success and containing an #error directive on failure.
Within your C code, you could additionally assure that the size of your struct matches:
#define CONCATENATE(X, Y) CONCATENATE_(X, Y)
#define CONCATENATE_(X, Y) X##Y
#define STATIC_ASSERT(CONDITION) \
typedef int(CONCATENATE(_static_assert_, __LINE__))[(CONDITION)? 1 : -1]
STATIC_ASSERT(sizeof(struct errors) == sizeof(unsigned char));
The macro is defined to be re-usable, as is, though, might produce additional warnings if used within function body (because of unused local type).
I am somewhat new to C in regards to structures, unions and bitfields and need help. Below is the SLPH_CONTROL which will "control" the bits in the destination of DRVCONF0 and DRVCONF1. After the code snippet I will explain what I need.
/* SLPH_CONTROL **********************************************/
typedef union
{
struct
{
unsigned int SH0_BIT0 :1;
unsigned int SH0_BIT1 :1;
};
uint8 SLPH_CONTROL_byte;
} SLPH_CONTROL;
SLPH_CONTROL my_SLPH_CONTROL;
/* DRVCONF0 **********************************************/
typedef union
{
struct
{
unsigned int DF0_BIT0 :1;
unsigned int DF0_BIT1 :1;
unsigned int DF0_BIT2 :1;
unsigned int DF0_BIT3 :1;
unsigned int DF0_BIT4 :1;
};
uint8 DRVCONF0_byte;
} DRVCONF0;
DRVCONF0 my_DRVCONF0;
/* DRVCONF0 **********************************************/
typedef union
{
struct
{
unsigned int DF1_BIT0 :1;
unsigned int DF1_BIT1 :1;
unsigned int DF1_BIT2 :1;
unsigned int DF1_BIT3 :1;
unsigned int DF1_BIT4 :1;
};
uint8 DRVCONF1_byte;
} DRVCONF1;
DRVCONF1 my_DRVCONF1;
Now with the code above I want to link or copy data from and to like so:
SH0_BIT0:1 to DF0_BIT4:1;
SH1_BIT1:1 to DF1_BIT0:1;
Is there a way to do this? I am really lost and looked everywhere online for a solution to this. Any suggestions are welcome!!!
Thanks,
Eric
Maybe this is possible on special embedded H/W (I don't know) but not on a regular PC with standard C.
Bit fields describe individual bits in one or more consecutive bytes. Actually, bytes are addressable but bits are not. The read/write access to bits is internally solved by bit-wise operations (like in C expressed with &, |, ^, ~).
my_DRVCONF0 and my_DRVCONF1 are individual variables in your sample. Thus, it's even not granted that they will be allocated/stored in consecutive memory. (They definitely will not if some kind of word-alignment is enabled.)
You probably have to make the control more sophisticated (e.g. providing pairs of address and bit index) to do what's intended.
I have a problem when using memcpy on a struct.
Consider the following struct
struct HEADER
{
unsigned int preamble;
unsigned char length;
unsigned char control;
unsigned int destination;
unsigned int source;
unsigned int crc;
}
If I use memcpy to copy data from a receive buffer to this struct the copy is OK, but if i redeclare the struct to the following :
struct HEADER
{
unsigned int preamble;
unsigned char length;
struct CONTROL control;
unsigned int destination;
unsigned int source;
unsigned int crc;
}
struct CONTROL
{
unsigned dir : 1;
unsigned prm : 1;
unsigned fcb : 1;
unsigned fcb : 1;
unsigned function_code : 4;
}
Now if I use the same memcpy code as before, the first two variables ( preamble and length ) are copied OK. The control is totally messed up, and last three variables are shifted one up, aka crc = 0, source = crc, destination = source...
ANyone got any good suggestions for me ?
Do you know that the format in the receive buffer is correct, when you add the control in the middle?
Anyway, your problem is that bitfields are the wrong tool here: you can't depend on the layout in memory being anything in particular, least of all the exact same one you've chosen for the serialized form.
It's almost never a good idea to try to directly copy structures to/from external storage; you need proper serialization. The compiler can add padding and alignment between the fields of a structure, and using bitfields makes it even worse. Don't do this.
Implement proper serialization/deserialization functions:
unsigned char * header_serialize(unsigned char *put, const struct HEADER *h);
unsigned char * header_deserialize(unsigned char *get, struct HEADER *h);
That go through the structure and read/write as many bytes as you feel are needed (possibly for each field):
static unsigned char * uint32_serialize(unsigned char *put, uint32_t x)
{
*put++ = (x >> 24) & 255;
*put++ = (x >> 16) & 255;
*put++ = (x >> 8) & 255;
*put++ = x & 255;
return put;
}
unsigned char * header_serialize(unsigned char *put, const struct HEADER *h)
{
const uint8_t ctrl_serialized = (h->control.dir << 7) |
(h->control.prm << 6) |
(h->control.fcb << 5) |
(h->control.function_code);
put = uint32_serialize(put, h->preamble);
*put++ = h->length;
*put++ = ctrl_serialized;
put = uint32_serialize(put, h->destination);
put = uint32_serialize(put, h->source);
put = uint32_serialize(put, h->crc);
return put;
}
Note how this needs to be explicit about the endianness of the serialized data, which is something you always should care about (I used big-endian). It also explicitly builds a single uint8_t version of the control fields, assuming the struct version was used.
Also note that there's a typo in your CONTROL declaration; fcb occurs twice.
Using struct CONTROL control; instead of unsigned char control; leads to a different alignment inside the struct and so filling it with memcpy() produces a different result.
Memcpy copies the values of bytes from the location pointed by source directly to the memory block pointed by destination.
The underlying type of the objects pointed by both the source and destination pointers are irrelevant for this function; The result is a binary copy of the data.
So if there is any structure padding then you will have messed up results.
Check sizeof(struct CONTROL) -- I think it would be 2 or 4 depending on the machine. Since you are using unsigned bitfields (and unsigned is shorthand of unsigned int), the whole structure (struct CONTROL) would take at least the size of unsigned int -- i.e. 2 or 4 bytes.
And, using unsigned char control takes 1 byte for this field. So, definitely there should be mismatch staring with the control variable.
Try rewriting the struct control as below:-
struct CONTROL
{
unsigned char dir : 1;
unsigned char prm : 1;
unsigned char fcb : 1;
unsigned char fcb : 1;
unsigned char function_code : 4;
}
The clean way would be to use a union, like in.:
struct HEADER
{
unsigned int preamble;
unsigned char length;
union {
unsigned char all;
struct CONTROL control;
} uni;
unsigned int destination;
unsigned int source;
unsigned int crc;
};
The user of the struct can then choose the way he wants to access the thing.
struct HEADER thing = {... };
if (thing.uni.control.dir) { ...}
or
#if ( !FULL_MOON ) /* Update: stacking of bits within a word appears to depend on the phase of the moon */
if (thing.uni.all & 1) { ... }
#else
if (thing.uni.all & 0x80) { ... }
#endif
Note: this construct does not solve endianness issues, that will need implicit conversions.
Note2: and you'll have to check the bit-endianness of your compiler, too.
Also note that bitfields are not very useful, especially if the data goes over the wire, and the code is expected to run on different platforms, with different alignment and / or endianness. Plain unsigned char or uint8_t plus some bitmasking yields much cleaner code. For example, check the IP stack in the BSD or linux kernels.
I have used bit field with a structure like this,
struct
{
unsigned int is_static: 1;
unsigned int is_extern: 1;
unsigned int is_auto: 1;
} flags;
Now i wondered to see if this can be done with a union so i modified the code like,
union
{
unsigned int is_static: 1;
unsigned int is_extern: 1;
unsigned int is_auto: 1;
} flags;
I found the bit field with union works but all those fields in the union are given to a single bit as I understood from output. Now I am seeing it is not erroneous to use bit fields with union, but it seems to me that using it like this is not operationally correct. So what is the answer - is it valid to use bit field with union?
It is valid but as you found out, not useful the way you have done it there.
You might do something like this so you can reset all the bits at the same time using flags.
union {
struct {
unsigned int is_static: 1;
unsigned int is_extern: 1;
unsigned int is_auto: 1;
};
unsigned int flags;
};
Or you might do something like this:
union {
struct {
unsigned int is_static: 1;
unsigned int is_extern: 1;
unsigned int is_auto: 1;
};
struct {
unsigned int is_ready: 1;
unsigned int is_done: 1;
unsigned int is_waiting: 1;
};
};
You are given a gun and bullets. Is it okay to shoot your self in foot with it? Of course not, but nobody can stop you from doing this if you want to.
My point is, just like gun and bullets, union and bit fields are tools and they have their purpose, uses and "abuses". So using bitfields in union, as you have written above, is perfectly valid C but a useless piece of code. All the fields inside union share same memory so all the bitfields you mention are essentially same flag as they share same memory.
Here is an example on how to use bit fields with unions. I'm also showing how to arrange for MSB. In pictures it would look something like this:
MSB LSB
7 0
+------+-------+
| five | three |
| bits | bits |
+------+-------+
// A struct tag definition of
// two bit fields in an 8-bit register
struct fields_tag {
// LSB
unsigned int five:5;
unsigned int three:3;
// MSB
};
// here is a tag and typedef for less typing
// to modify the 8-bit value as a whole
// and read in parts.
typedef union some_reg_tag {
uint8_t raw;
struct fields_tag fields;
} some_reg_t;
Here is how to use the bit fields with Arduino
some_reg_t a_register;
a_register.raw = 0xC2; // assign using raw field.
Serial.print("some reg = "); // dump entire register
Serial.println(a_register.raw, HEX); // dump register by field
Serial.print("some reg.three = ");
Serial.println(a_register.fields.three, HEX);
Serial.print("some reg.five = ");
Serial.println(a_register.fields.five, HEX);
Here is the output showing the results
some reg = C2
some reg.three = 6
some reg.five = 2
I am trying to make a structure for a data packet that has a dynamic payload length and is determined by a variable within the header struct (LEN).
I am unsure on how to do this properly and I am confused by some of the examples that i have come across. Bellow is the Structure that is the basis of what i will be using.
Thanks.
struct packet
{
unsigned char payload;
unsigned int CRC : 16;
struct header
{
unsigned char SRC;
unsigned char DST;
unsigned char NS : 3; //3 bits long
unsigned char NR : 3;
unsigned char RSV : 1; //1 bit long
unsigned char LST : 1;
unsigned char OP;
unsigned char LEN;
} HEADER;
};
struct packet PACKET;
You can use a construct sometimes referred to as a "stretchy array". (Or as #Jerry Coffin points out, a "flexible array member") The variable-length payload needs to be at the end:
struct packet
{
struct header
{
unsigned char SRC;
unsigned char DST;
unsigned char NS : 3; //3 bits long
unsigned char NR : 3;
unsigned char RSV : 1; //1 bit long
unsigned char LST : 1;
unsigned char OP;
unsigned char LEN;
} HEADER;
unsigned int CRC : 16;
unsigned char payload[1]; //STRETCHY.
};
struct packet PACKET;
This type of structure needs to be dynamically allocated, since you need to manually make enough room for the payload.
PACKET * p = malloc( sizeof(PACKET)+payloadLength*sizeof(char) );
p->HEADER->LEN = payloadLength;
//fill in rest of header here.
memcpy(p->payload, incomingData, payloadLength);
Make the payload a pointer instead and allocate it at runtime according to the value of LEN in the header field.
You need to include the length in your struct but not the data. Depending on what you are doing you handle the data differently. The struct should probably contain a pointer to the data but you have to handle this when you serialize deserialize the struct. That is the pointer will mean nothing when you read it back in.
So you write the struct out including the size of the data field, then the data field out. When you read it back you fscanf the struct, then read the size of bytes the struct tells you to from the stream and store that as your data, and then finally store a pointer to the newly read data in the struct that was created with fscanf. If you are reading in multiple items like this you can continue at that point reading the next struct then data and so on.