106 lines
3.6 KiB
C
Executable File
106 lines
3.6 KiB
C
Executable File
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
//#include <asm/unaligned.h>
|
|
#include <string.h>
|
|
#include "dns_construct.h"
|
|
|
|
#define get_unaligned(ptr) \
|
|
({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
|
|
|
|
#define put_unaligned(val, ptr) \
|
|
({ __typeof__(*(ptr)) __tmp = (val); \
|
|
memmove((ptr), &__tmp, sizeof(*(ptr))); \
|
|
(void)0; })
|
|
|
|
#define SET_UINT16_TO_N(buf, val, count) put_unaligned(htons(val), (uint16*)buf);count += 2; buf += 2
|
|
#define SET_UINT32_TO_N(buf, val, count) put_unaligned(htonl(val), (uint32*)buf);count += 4; buf += 4
|
|
/*****************************************************************************/
|
|
/* this function encode the plain string in name to the domain name encoding
|
|
* see decode_domain_name for more details on what this function does. */
|
|
int dns_construct_name(char *name, char *encoded_name)
|
|
{
|
|
int i,j,k,n;
|
|
|
|
k = 0; /* k is the index to temp */
|
|
i = 0; /* i is the index to name */
|
|
while( name[i] ){
|
|
|
|
/* find the dist to the next '.' or the end of the string and add it*/
|
|
for( j = 0; name[i+j] && name[i+j] != '.'; j++);
|
|
encoded_name[k++] = j;
|
|
|
|
/* now copy the text till the next dot */
|
|
for( n = 0; n < j; n++)
|
|
encoded_name[k++] = name[i+n];
|
|
|
|
/* now move to the next dot */
|
|
i += j + 1;
|
|
|
|
/* check to see if last dot was not the end of the string */
|
|
if(!name[i-1])break;
|
|
}
|
|
encoded_name[k++] = 0;
|
|
return k;
|
|
}
|
|
/*****************************************************************************/
|
|
int dns_construct_header(dns_request_t *m)
|
|
{
|
|
char *ptr = m->original_buf;
|
|
int dummy;
|
|
|
|
SET_UINT16_TO_N( ptr, m->message.header.id, dummy );
|
|
SET_UINT16_TO_N( ptr, m->message.header.flags.flags, dummy );
|
|
SET_UINT16_TO_N( ptr, m->message.header.qdcount, dummy );
|
|
SET_UINT16_TO_N( ptr, m->message.header.ancount, dummy );
|
|
SET_UINT16_TO_N( ptr, m->message.header.nscount, dummy );
|
|
SET_UINT16_TO_N( ptr, m->message.header.arcount, dummy );
|
|
|
|
return 0;
|
|
}
|
|
/*****************************************************************************/
|
|
void dns_construct_reply( dns_request_t *m )
|
|
{
|
|
int len;
|
|
|
|
/* point to end of orginal packet */
|
|
m->here = &m->original_buf[m->numread];
|
|
|
|
m->message.header.ancount = 1;
|
|
m->message.header.flags.f.question = 1;
|
|
dns_construct_header( m );
|
|
|
|
if( m->message.question[0].type == A ){
|
|
/* standard lookup so return and IP */
|
|
struct in_addr in;
|
|
|
|
inet_aton( m->ip, &in );
|
|
SET_UINT16_TO_N( m->here, 0xc00c, m->numread ); /* pointer to name */
|
|
SET_UINT16_TO_N( m->here, A, m->numread ); /* type */
|
|
SET_UINT16_TO_N( m->here, IN, m->numread ); /* class */
|
|
SET_UINT32_TO_N( m->here, 10000, m->numread ); /* ttl */
|
|
SET_UINT16_TO_N( m->here, 4, m->numread ); /* datalen */
|
|
memcpy( m->here, &in.s_addr, sizeof(in.s_addr) ); /* data */
|
|
m->numread += sizeof( in.s_addr);
|
|
}else if ( m->message.question[0].type == PTR ){
|
|
/* reverse look up so we are returning a name */
|
|
SET_UINT16_TO_N( m->here, 0xc00c, m->numread ); /* pointer to name */
|
|
SET_UINT16_TO_N( m->here, PTR, m->numread ); /* type */
|
|
SET_UINT16_TO_N( m->here, IN, m->numread ); /* class */
|
|
SET_UINT32_TO_N( m->here, 10000, m->numread ); /* ttl */
|
|
len = dns_construct_name( m->cname, m->here + 2 );
|
|
SET_UINT16_TO_N( m->here, len, m->numread ); /* datalen */
|
|
m->numread += len;
|
|
}
|
|
}
|
|
/*****************************************************************************/
|
|
void dns_construct_error_reply(dns_request_t *m)
|
|
{
|
|
/* point to end of orginal packet */
|
|
m->here = m->original_buf;
|
|
|
|
m->message.header.flags.f.question = 1;
|
|
m->message.header.flags.f.rcode = 2;
|
|
dns_construct_header( m );
|
|
}
|