1. dns query

Hi everyone, i'm a university student and i have been asked to write a dns query program in C.

We have to create the packet header by manipulating the bits of a 12 character array.

I have searched the internet and come up woth nothing so far to help me.

Unfortunately, i have got nothing with regards to creating the query header so far.

Im sure that if i can get some help on the first few things i can work out the rest, or at least be able to progress, but at the moment i dont really know where to start.

So far i have created the array, and memset it to all '0's

I know then i have to change individual bits to show the identification, whether it is a query or response, etc etc.

Im just not sure how i go about changing the bits in each character of the array.

Any help would be greatly appreciated

2. Im just not sure how i go about changing the bits in each character of the array.
There are CHAR_BIT bits in a character, you can find CHAR_BIT in <limits.h>. From there it's just a matter of knowing which bit to look at and what operation to perform on it to do what you want. There are really only three operations you can perform on a single bit: test if it's set, set it and clear it.

Here are a few macros that perform those operations.
Code:
```#define bit(i) (1U << (i))
#define test(x, i) (((x) & bit((i))) != 0)
#define set(x, i) ((x) = (x) | bit((i)))
#define clear(x, i) ((x) = (x) &= ~bit((i)))```

3. Don't know if you've seen this Beej's Guide but it should help.

Code:
```#include <stdio.h>

int main (void)
{
unsigned char a=0;
printf("Before %u\n",(unsigned int)a);
a = 0x01 | 0xf0;
/* 0x01 = 00000001 or decimal 1,
* 0xf0 = 11110000 or decimal 240 unsigned or -16 signed
* Result should be 11110001 or 241 Unsigned*/
printf("After %u\n", (unsigned int)a);

return 0;
}```
Quick definations: | is a bitwise OR operator. So say you | two numbers that have the bit patterns of 0101 and 1100 together the result will be 1101. & is a bitwise AND operator so with the previous example the result would be 0100.

Quick Hex to Binary:
0x0 = 0000
0x1 = 0001
0x2 = 0010
0x3 = 0011
0x4 = 0100
0x5 = 0101
0x6 = 0110
0x7 = 0111
0x8 = 1000
0x9 = 1001
0xA = 1010
0xB = 1011
0xC = 1100
0xD = 1101
0xE = 1110
0xF = 1111

4. Thanks for the replies guys, , a few further questions though.

As an example im trying to write a function that will set the QR (query or response) field of the header,

incase you dont know the structure of the dns header, i posted the image below, that shows it

Code:
```void SetQuery(unsigned char * header){
}```
ok, i think this code will set the 2nd character to all '0's but i only want to set the first bit,

the opcode also is in the 2nd character, but the next 4 bits, how would i set them specifically to a number passed in to the function as an argument.

thanks again for all your help guys

5. >ok, i think this code will set the 2nd character to all '0's but i only want to set the first bit
This is where the bit macros I showed you come in handy. You can make it as simple as this.
Code:
`set(header[2], 0);`
Use & to mask off certain bits in a value, shift the value you want to replace with by the number of off bits and OR them together. Try 0xE1 as the mask for bits 2-5.
Code:
```#include <stdio.h>

int main(void)
{
unsigned char c = 0xFF;
unsigned char d = 0xA;

printf("%#x\n", (c & mask) | (d << 1));

return 0;
}```

6. Here is the packet struct for a dns resolver I made:
Code:
```/* DNS Header common to queries and answers
* This structure starts at byte 0 for udp packets */
typedef struct tagDnsHdr {

/* id of this request - used by application to match queries
* with replies - usually process id, but can be anything */
short id;

/* Note: We could do flags with bit fields but then we have
* to declare them twice. Once for little endian and once
* for big endian layout */

/* First byte of flags. Contains the following fields:
* QR (1 bit), OPCODE(4 bits), AA(1 bit), TC(1 bit), RD(1 bit)
* These can be set or retrieved using the bit mask constants
* eg. DNSHDR.lFlags |= BITS_RD to set.
* and to retrieve: trunc = DNSHDR.lFlags & BITS_TC
unsigned char lFlags;

/* Second byte of flags. Contains the following fields:
* RA (1 bit), Z(3 bits), RCODE(4 bits)
* Note: Z is marked as reserved in rfc 1035 */
unsigned char rFlags;

unsigned short qCount;  /* query count */
unsigned short anCount; /* answer count - return value only */
unsigned short nsCount; /* name server count - return value only */
unsigned short arCount; /* additional records count - return value only */

} DNSHDR;

/* zero for a query, one for a response */
#define BITS_QR  128

/* usually zero for a standard query */
#define BITS_OPCODE  120

/* 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. */
#define BITS_AA  4

/* Set if the answer has been truncated for being over the
* 512 byte limit (udp only) */
#define BITS_TC  2

/* Recursion desired - Should be set in the query */
#define BITS_RD  1

/* Recursion available - set by server if it was able
* to use recursion */
#define BITS_RA  128

/* Reserved - should be zero */
#define BITS_Z  112

/* The response code is returned by the server */
#define BITS_RCODE  15```
If I was doing this again I would use bitfields. Also, I would use types such as int16_t for maximum portability.

I could post my complete code but here is a much better example:
http://www.planet-source-code.com/vb...txtCodeId=5712

Search for dns.c for other examples.

NB. Buffer overruns are extremely easy to miss in a dns resolver, so if you don't want the dns server to be able to execute code on your machine be careful.

EDIT:
Bitfield example - PCs are little endian, Unix is typically big endian.

7. cheers for all the help guys

i think im starting to understand all this now

im gonna go off and have a play and hopefully all will be well,

thanks once again everyone