/*
* $Id: nemesis-proto_dns.c,v 1.1.1.1 2003/10/31 21:29:37 jnathan Exp $
*
* THE NEMESIS PROJECT
* Copyright (C) 1999, 2000, 2001 Mark Grimes <mark@stateful.net>
* Copyright (C) 2001 - 2003 Jeff Nathan <jeff@snort.org>
*
* nemesis-proto_dns.c (DNS Packet Generator)
*
*/
#include "nemesis-dns.h"
#include "nemesis.h"
int builddns(ETHERhdr *eth, IPhdr *ip, TCPhdr *tcp, UDPhdr *udp, DNShdr *dns,
FileData *pd, FileData *ipod, FileData *tcpod, char *device)
{
int n;
u_int32_t dns_packetlen = 0, dns_meta_packetlen = 0;
static u_int8_t *pkt;
static int sockfd = -1;
struct libnet_link_int *l2 = NULL;
u_int8_t link_offset = 0;
#if !defined(WIN32)
int sockbuff = IP_MAXPACKET;
#endif
if (pd->file_mem == NULL)
pd->file_s = 0;
if (ipod->file_mem == NULL)
ipod->file_s = 0;
if (tcpod->file_mem == NULL)
tcpod->file_s = 0;
if (got_link) /* data link layer transport */
{
if ((l2 = libnet_open_link_interface(device, errbuf)) == NULL)
{
nemesis_device_failure(INJECTION_LINK, (const char *)device);
return -1;
}
link_offset = LIBNET_ETH_H;
}
else
{
if ((sockfd = libnet_open_raw_sock(IPPROTO_RAW)) < 0)
{
nemesis_device_failure(INJECTION_RAW, (const char *)NULL);
return -1;
}
#if !defined(WIN32)
if ((setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const void *)&sockbuff,
sizeof(sockbuff))) < 0)
{
fprintf(stderr, "ERROR: setsockopt() failed.\n");
return -1;
}
#endif
}
dns_packetlen = link_offset + LIBNET_IP_H + LIBNET_DNS_H + pd->file_s +
ipod->file_s;
if (state == 0) /* UDP */
dns_packetlen += LIBNET_UDP_H;
else /* TCP */
dns_packetlen += LIBNET_TCP_H + tcpod->file_s;
dns_meta_packetlen = dns_packetlen - (link_offset + LIBNET_IP_H);
#ifdef DEBUG
printf("DEBUG: DNS packet length %u.\n", dns_packetlen);
printf("DEBUG: IP options size %u.\n", ipod->file_s);
printf("DEBUG: TCP options size %u.\n", tcpod->file_s);
printf("DEBUG: DNS payload size %u.\n", pd->file_s);
#endif
if (libnet_init_packet(dns_packetlen, &pkt) == -1)
{
fprintf(stderr, "ERROR: Unable to allocate packet memory.\n");
return -1;
}
if (got_link)
libnet_build_ethernet(eth->ether_dhost, eth->ether_shost,
ETHERTYPE_IP, NULL, 0, pkt);
libnet_build_ip(dns_meta_packetlen, ip->ip_tos, ip->ip_id,
ip->ip_off, ip->ip_ttl, ip->ip_p, ip->ip_src.s_addr,
ip->ip_dst.s_addr, NULL, 0, pkt + link_offset);
if (state == 0)
{
libnet_build_udp(udp->uh_sport, udp->uh_dport, NULL, 0,
pkt + link_offset + LIBNET_IP_H);
}
else
{
libnet_build_tcp(tcp->th_sport, tcp->th_dport, tcp->th_seq,
tcp->th_ack, tcp->th_flags, tcp->th_win, tcp->th_urp,
NULL, 0, pkt + link_offset + LIBNET_IP_H);
}
libnet_build_dns(dns->id, dns->flags, dns->num_q, dns->num_answ_rr,
dns->num_auth_rr, dns->num_addi_rr, pd->file_mem,
pd->file_s, pkt + link_offset + LIBNET_IP_H + ((state == 0) ?
LIBNET_UDP_H : LIBNET_TCP_H));
if (got_ipoptions)
{
if ((libnet_insert_ipo((struct ipoption *)ipod->file_mem,
ipod->file_s, pkt + link_offset)) == -1)
{
fprintf(stderr, "ERROR: Unable to add IP options, discarding "
"them.\n");
}
}
if (state == 1)
{
if (got_tcpoptions)
{
if ((libnet_insert_tcpo((struct tcpoption *)tcpod->file_mem,
tcpod->file_s, pkt + link_offset)) == -1)
{
fprintf(stderr, "ERROR: Unable to add TCP options, discarding "
"them.\n");
}
}
}
if (got_link)
libnet_do_checksum(pkt + LIBNET_ETH_H, IPPROTO_IP, LIBNET_IP_H +
ipod->file_s);
libnet_do_checksum(pkt + link_offset, ((state == 0) ? IPPROTO_UDP :
IPPROTO_TCP), ((state == 0) ? LIBNET_UDP_H : LIBNET_TCP_H) +
LIBNET_DNS_H + pd->file_s + ipod->file_s +
((state == 0) ? 0: tcpod->file_s));
if (got_link)
n = libnet_write_link_layer(l2, device, pkt, dns_packetlen);
else
n = libnet_write_ip(sockfd, pkt, dns_packetlen);
if (verbose == 2)
nemesis_hexdump(pkt, dns_packetlen, HEX_ASCII_DECODE);
if (verbose == 3)
nemesis_hexdump(pkt, dns_packetlen, HEX_RAW_DECODE);
if (n != dns_packetlen)
{
fprintf(stderr, "ERROR: Incomplete packet injection. Only wrote %d "
"bytes.\n", n);
}
else
{
if (verbose)
{
if (got_link)
{
printf("Wrote %d byte DNS (%s) packet through "
"linktype %s.\n", n, ((state == 0) ? "UDP" : "TCP"),
nemesis_lookup_linktype(l2->linktype));
}
else
{
printf("Wrote %d byte DNS (%s) packet\n", n,
((state == 1) ? "UDP" : "TCP"));
}
}
}
libnet_destroy_packet(&pkt);
if (got_link)
libnet_close_link_interface(l2);
else
libnet_close_raw_sock(sockfd);
return n;
}
syntax highlighted by Code2HTML, v. 0.9.1