blob: d7557bf70dd0554e7816fdb0dcb1d877c152b686 [file] [log] [blame]
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <ctype.h>
#include "DNSCommon.h"
#ifdef FUZZING_SETRDATA
#ifdef JUST_FOR_REFERENCE
typedef struct
{
DNSMessageHeader h; // Note: Size 12 bytes
mDNSu8 data[AbsoluteMaxDNSMessageData]; // 40 (IPv6) + 8 (UDP) + 12 (DNS header) + 8940 (data) = 9000
} DNSMessage;
struct ResourceRecord_struct
{
mDNSu8 RecordType; // See kDNSRecordTypes enum.
mDNSu8 negativeRecordType; // If RecordType is kDNSRecordTypePacketNegative, specifies type of negative record.
MortalityState mortality; // Mortality of this resource record (See MortalityState enum)
mDNSu16 rrtype; // See DNS_TypeValues enum.
mDNSu16 rrclass; // See DNS_ClassValues enum.
mDNSu32 rroriginalttl; // In seconds
mDNSu16 rdlength; // Size of the raw rdata, in bytes, in the on-the-wire format
// (In-memory storage may be larger, for structures containing 'holes', like SOA)
mDNSu16 rdestimate; // Upper bound on on-the-wire size of rdata after name compression
mDNSu32 namehash; // Name-based (i.e. case-insensitive) hash of name
mDNSu32 rdatahash; // For rdata containing domain name (e.g. PTR, SRV, CNAME etc.), case-insensitive name hash
// else, for all other rdata, 32-bit hash of the raw rdata
// Note: This requirement is important. Various routines like AddAdditionalsToResponseList(),
// ReconfirmAntecedents(), etc., use rdatahash as a pre-flight check to see
// whether it's worth doing a full SameDomainName() call. If the rdatahash
// is not a correct case-insensitive name hash, they'll get false negatives.
// Grouping pointers together at the end of the structure improves the memory layout efficiency
mDNSInterfaceID InterfaceID; // Set if this RR is specific to one interface
// For records received off the wire, InterfaceID is *always* set to the receiving interface
// For our authoritative records, InterfaceID is usually zero, except for those few records
// that are interface-specific (e.g. address records, especially linklocal addresses)
domainname *name;
RData *rdata; // Pointer to storage for this rdata
#if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
mdns_dns_service_t dnsservice;
mdns_resolver_type_t protocol;
#else
DNSServer *rDNSServer; // Unicast DNS server authoritative for this entry; null for multicast
#endif
};
typedef struct { mDNSu8 c[256]; } domainname;
typedef struct
{
mDNSu16 MaxRDLength; // Amount of storage allocated for rdata (usually sizeof(RDataBody))
mDNSu16 padding; // So that RDataBody is aligned on 32-bit boundary
RDataBody u;
} RData;
#endif
// #define min(x,y) (x<y ? x : y)
int LLVMFuzzerTestOneInput(char* Data, size_t Length)
{
if(Length < 3) {
return 0;
}
// First three bytes are type and length
// We have to use a two-byte length, since RDataBody2 is pretty big
uint8_t recordType = (uint8_t) Data[0];
uint16_t rdlen = *(uint16_t*)&Data[1];
rdlen &= 0x7ff;
Data += 3;
Length -= 3;
// Make sure not to go over MTU size
if(rdlen > AbsoluteMaxDNSMessageData) {
return 0;
}
// Make sure we have enough data for everything else
if(Length < rdlen + sizeof(domainname)) {
return 0;
}
// Fill the domainname with random data
domainname *name = malloc(sizeof(*name));
memcpy(name, Data, sizeof(*name));
Data += sizeof(*name);
Length -= sizeof(*name);
// Allocate an RData object of variable length
size_t rdcapacity = (rdlen > sizeof(RDataBody2)) ? rdlen : sizeof(RDataBody2);
RData *rdata = malloc((sizeof(RData) - sizeof(RDataBody)) + rdcapacity);
rdata->MaxRDLength = (uint16_t) rdcapacity;
// Use a random record type
ResourceRecord *rr = malloc(sizeof(*rr));
rr->rrtype = recordType;
rr->name = name;
rr->rdata = rdata;
// Check against the number of bytes we have
if(Length >= rdlen) {
// The rest of the buffer goes as input
uint8_t *buffer = malloc(rdlen);
uint8_t *end = (uint8_t*) buffer + rdlen;
memcpy(buffer, Data, rdlen);
// SetRData copies the record data out of "buffer" and into "rr.rdata"
SetRData(0, buffer, end, rr, rdlen);
free(buffer);
}
free(rr);
free(name);
free(rdata);
return 0;
}
#endif