@echo "const char gsGitHash[] = \"$(_GITHASH)\";" >> $@
@echo "const int giBuildNumber = $(BUILD_NUM);" >> $@
@echo "const char gsBuildInfo[] = \"Acess2 v$(KERNEL_VERSION) $(ARCH)-$(PLATFORM)\\\\r\\\\n\"" >> $@
- @echo " \"Build $(shell hostname --fqdn):$(BUILD_NUM) Git $(_GITHASH) - $(_GITCHANGED) modified\";" >> $@
+ @echo " \"Build $(shell hostname --fqdn):$(BUILD_NUM) $(shell date +%FT%T%z) Git $(_GITHASH) - $(_GITCHANGED) modified\";" >> $@
# Compile rule for buildinfo (needs a special one because it's not a general source file)
$(BUILDINFO_OBJ): $(BUILDINFO_SRC)
@echo --- CC -o $@
int UDP_int_ScanList(tUDPChannel *List, tInterface *Interface, void *Address, int Length, void *Buffer)
{
tUDPHeader *hdr = Buffer;
- tUDPChannel *chan;
- tUDPPacket *pack;
- int len;
- for(chan = List; chan; chan = chan->Next)
+ for(tUDPChannel *chan = List; chan; chan = chan->Next)
{
// Match local endpoint
+ LOG("(%p):%i - %s/%i:%i",
+ chan->Interface, chan->LocalPort,
+ IPStack_PrintAddress(chan->Remote.AddrType, &chan->Remote.Addr), chan->RemoteMask,
+ chan->Remote.Port
+ );
if(chan->Interface && chan->Interface != Interface) continue;
if(chan->LocalPort != ntohs(hdr->DestPort)) continue;
Log_Log("UDP", "Recieved packet for %p", chan);
// Create the cached packet
- len = ntohs(hdr->Length);
- pack = malloc(sizeof(tUDPPacket) + len);
+ int len = ntohs(hdr->Length);
+ tUDPPacket *pack = malloc(sizeof(tUDPPacket) + len);
pack->Next = NULL;
memcpy(&pack->Remote.Addr, Address, IPStack_GetAddressSize(Interface->Type));
pack->Remote.Port = ntohs(hdr->SourcePort);
{
tUDPHeader hdr;
- if(Channel->Interface && Channel->Interface->Type != AddrType) return ;
+ if(Channel->Interface && Channel->Interface->Type != AddrType) {
+ LOG("Bad interface type for channel packet, IF is %i, but packet is %i",
+ Channel->Interface->Type, AddrType);
+ return ;
+ }
// Create the packet
hdr.SourcePort = htons( Channel->LocalPort );
IPStack_Buffer_AppendSubBuffer(buffer, Length, 0, Data, NULL, NULL);
IPStack_Buffer_AppendSubBuffer(buffer, sizeof(hdr), 0, &hdr, NULL, NULL);
// TODO: What if Channel->Interface is NULL here?
+ ASSERT(Channel->Interface);
IPv4_SendPacket(Channel->Interface, *(tIPv4*)Address, IP4PROT_UDP, 0, buffer);
break;
default:
return &new->Node;
}
-/**
- * \brief Read from the channel file (wait for a packet)
- */
-size_t UDP_Channel_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
+tUDPPacket *UDP_Channel_WaitForPacket(tUDPChannel *chan, Uint VFSFlags)
{
- tUDPChannel *chan = Node->ImplPtr;
- tUDPPacket *pack;
- tUDPEndpoint *ep;
- int ofs, addrlen;
-
- if(chan->LocalPort == 0) {
- Log_Notice("UDP", "Channel %p sent with no local port", chan);
- return 0;
- }
-
- while(chan->Queue == NULL) Threads_Yield();
+ // EVIL - Yield until queue is created (avoids races)
+ while(chan->Queue == NULL)
+ Threads_Yield();
for(;;)
{
- tTime timeout_z = 0, *timeout = (Flags & VFS_IOFLAG_NOBLOCK) ? &timeout_z : NULL;
- int rv = VFS_SelectNode(Node, VFS_SELECT_READ, timeout, "UDP_Channel_Read");
- if( rv ) {
- errno = (Flags & VFS_IOFLAG_NOBLOCK) ? EWOULDBLOCK : EINTR;
+ tTime timeout_z = 0, *timeout = (VFSFlags & VFS_IOFLAG_NOBLOCK) ? &timeout_z : NULL;
+ int rv = VFS_SelectNode(&chan->Node, VFS_SELECT_READ, timeout, "UDP_Channel_Read");
+ if( rv == 0 ) {
+ errno = (VFSFlags & VFS_IOFLAG_NOBLOCK) ? EWOULDBLOCK : EINTR;
+ return NULL;
}
SHORTLOCK(&chan->lQueue);
if(chan->Queue == NULL) {
SHORTREL(&chan->lQueue);
continue;
}
- pack = chan->Queue;
+ tUDPPacket *pack = chan->Queue;
chan->Queue = pack->Next;
if(!chan->Queue) {
chan->QueueEnd = NULL;
- VFS_MarkAvaliable(Node, 0); // Nothing left
+ VFS_MarkAvaliable(&chan->Node, 0); // Nothing left
}
SHORTREL(&chan->lQueue);
- break;
+ return pack;
+ }
+ // Unreachable
+}
+
+/**
+ * \brief Read from the channel file (wait for a packet)
+ */
+size_t UDP_Channel_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
+{
+ tUDPChannel *chan = Node->ImplPtr;
+
+ if(chan->LocalPort == 0) {
+ Log_Notice("UDP", "Channel %p sent with no local port", chan);
+ return 0;
+ }
+
+ tUDPPacket *pack = UDP_Channel_WaitForPacket(chan, Flags);
+ if( !pack ) {
+ return 0;
}
+ size_t addrlen = IPStack_GetAddressSize(pack->Remote.AddrType);
+ tUDPEndpoint *ep = Buffer;
+ size_t ofs = 4 + addrlen;
+
// Check that the header fits
- addrlen = IPStack_GetAddressSize(pack->Remote.AddrType);
- ep = Buffer;
- ofs = 4 + addrlen;
if(Length < ofs) {
free(pack);
Log_Notice("UDP", "Insuficient space for header in buffer (%i < %i)", (int)Length, ofs);
"getset_remoteport",
"getset_remotemask",
"set_remoteaddr",
+ "sendto",
+ "recvfrom",
NULL
};
/**
case 6: // getset_remotemask (returns bool success)
if(!Data) LEAVE_RET('i', chan->RemoteMask);
- if(!CheckMem(Data, sizeof(int))) LEAVE_RET('i', -1);
+ if(!CheckMem(Data, sizeof(int))) {
+ LOG("Data pointer invalid");
+ LEAVE_RET('i', -1);
+ }
if( !chan->Interface ) {
LOG("Can't set remote mask on NULL interface");
LEAVE_RET('i', -1);
}
- if( *(int*)Data > IPStack_GetAddressSize(chan->Interface->Type) )
+ int mask = *(int*)Data;
+ int addr_bits = IPStack_GetAddressSize(chan->Interface->Type) * 8;
+ if( mask > addr_bits ) {
+ LOG("Mask too large (%i > max %i)", mask, addr_bits);
LEAVE_RET('i', -1);
- chan->RemoteMask = *(int*)Data;
+ }
+ chan->RemoteMask = mask;
LEAVE('i', chan->RemoteMask);
return chan->RemoteMask;
LOG("Invalid pointer");
LEAVE_RET('i', -1);
}
+ LOG("Set remote addr %s", IPStack_PrintAddress(chan->Interface->Type, Data));
+ chan->Remote.AddrType = chan->Interface->Type;
memcpy(&chan->Remote.Addr, Data, IPStack_GetAddressSize(chan->Interface->Type));
LEAVE('i', 0);
return 0;
+ case 8: { // sendto
+ if(!CheckMem(Data, 2*sizeof(void*)+2)) {
+ LOG("Data pointer invalid");
+ LEAVE_RET('i', -1);
+ }
+ const struct sSendToArgs {
+ const tUDPEndpoint* ep;
+ const void* buf;
+ const Uint16 buflen;
+ } info = *(const struct sSendToArgs*)Data;
+ LOG("sendto(buf=%p + %u, ep=%p)", info.buf, info.buflen, info.ep);
+ if(!CheckMem(info.ep, 2+2) || !CheckMem(info.ep, 2+2+IPStack_GetAddressSize(info.ep->AddrType)) ) {
+ LEAVE_RET('i', -1);
+ }
+ if(!CheckMem(info.buf, info.buflen)) {
+ LEAVE_RET('i', -1);
+ }
+
+ UDP_SendPacketTo(chan, info.ep->AddrType, &info.ep->Addr, info.ep->Port,
+ info.buf, (size_t)info.buflen);
+
+ LEAVE_RET('i', info.buflen); }
+ case 9: { // recvfrom
+ if(!CheckMem(Data, 2*sizeof(void*)+2)) {
+ LOG("Data pointer invalid");
+ LEAVE_RET('i', -1);
+ }
+ const struct sRecvFromArgs {
+ tUDPEndpoint* ep;
+ void* buf;
+ Uint16 buflen;
+ } info = *(const struct sRecvFromArgs*)Data;
+ LOG("recvfrom(buf=%p + %u, ep=%p)", info.buf, info.buflen, info.ep);
+ if(!CheckMem(info.ep, 2+2)) {
+ LEAVE_RET('i', -1);
+ }
+ if(!CheckMem(info.buf, info.buflen)) {
+ LEAVE_RET('i', -1);
+ }
+
+ tUDPPacket *pack = UDP_Channel_WaitForPacket(chan, 0);
+ if( pack == NULL ) {
+ LOG("No packet");
+ LEAVE_RET('i', 0);
+ }
+
+ size_t addrsize = IPStack_GetAddressSize(pack->Remote.AddrType);
+ if( !CheckMem(info.ep, 2+2+addrsize) ) {
+ LOG("Insufficient space for source address");
+ free(pack);
+ LEAVE_RET('i', -1);
+ }
+ info.ep->Port = pack->Remote.Port;
+ info.ep->AddrType = pack->Remote.AddrType;
+ memcpy(&info.ep->Addr, &pack->Remote.Addr, addrsize);
+
+ size_t retlen = (info.buflen < pack->Length ? info.buflen : pack->Length);
+ memcpy(info.buf, pack->Data, retlen);
+
+ free(pack);
+
+ LEAVE_RET('i', retlen); }
}
LEAVE_RET('i', 0);
}
.PHONY: utest utest-build utest-run $(UTESTS:%=runtest-%)
-utest: utest-build generate_exp utest-run
-
-generate_exp: $(UTESTS:%=EXP_%.txt)
+utest: utest-build utest-run
utest-build: $(UTESTS:%=TEST_%)
utest-run: $(UTESTS:%=runtest-%)
-$(UTESTS:%=runtest-%): runtest-%: TEST_% EXP_%.txt
+$(UTESTS:%=runtest-%): runtest-%: TEST_%
@echo --- [TEST] $*
- @./TEST_$* | diff EXP_$*.txt -
+ @./TEST_$*
clean:
$(RM) $(_BIN) $(_XBIN) $(OBJ) $(_BIN).dsm $(DEPFILES) $(EXTRACLEAN)
OBJ += hostnames.o dns.o
BIN = libnet.so
+UTESTS = dns
+
include ../Makefile.tpl
--- /dev/null
+/*
+ */
+#include "include/dns.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdint.h>
+
+extern int DNS_int_ParseResponse(const void* packet, size_t return_len, void *info, handle_record_t* handle_record_t);
+
+// Complex response from "Q ssh.ucc.asn.au A IN"
+const uint8_t test_packet_1[] = {
+ 0xac, 0x00, 0x80, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x03, 0x73, 0x73, 0x68, 0x03, 0x75, 0x63, 0x63, 0x03, 0x61, 0x73, 0x6e, 0x02, 0x61, 0x75, 0x00, 0x00, 0x01, 0x00, 0x01, 0xc0, 0x18, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x01, 0x77, 0xc0, 0x18, 0xc0, 0x18, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x01, 0x78, 0xc0, 0x18, 0xc0, 0x18, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x01, 0x79, 0xc0, 0x18, 0xc0, 0x18, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x01, 0x61, 0xc0, 0x18, 0xc0, 0x18, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x01, 0x7a, 0xc0, 0x18, 0xc0, 0x18, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x01, 0x62, 0xc0, 0x18, 0xc0, 0x18, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x01, 0x75, 0xc0, 0x18, 0xc0, 0x18, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x01, 0x76, 0xc0, 0x18, 0xc0, 0x2c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x25, 0xd1, 0xc0, 0x05, 0xc0, 0x3c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x25, 0xd1, 0xc2, 0x05, 0xc0, 0x4c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x25, 0xd1, 0xc4, 0x05, 0xc0, 0x5c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x3a, 0x41, 0xfe, 0x49, 0xc0, 0x6c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x25, 0xd1, 0xc6, 0x05, 0xc0, 0x7c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0x3a, 0x41, 0xfd, 0x49, 0xc0, 0x8c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0xd3, 0x1d, 0x85, 0x20, 0xc0, 0x9c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xe6, 0xd6, 0x00, 0x04, 0xca, 0x0c, 0x1f, 0x8d,
+ };
+
+#define TEST_REL_INT(exp, rel, have) do { \
+ int a = (exp);\
+ int b = (have);\
+ if( !(a rel b) ) { \
+ fprintf(stderr, "TEST_REL_INT("#exp" "#rel" "#exp") FAILED l=%i r=%i", \
+ a, b); \
+ return 1; \
+ } \
+} while(0)
+
+int test_response_parse_1_cb(void *info, const char *name, enum eTypes type, enum eClass class, unsigned int ttl, size_t rdlength, const void *rdata)
+{
+ int* stagep = info;
+ switch( *stagep )
+ {
+ case 0:
+ TEST_REL_INT(0, ==, strcmp(name, "au."));
+ break;
+ }
+ (*stagep) += 1;
+ return 0;
+}
+int test_response_parse_1(void)
+{
+ int stage = 0;
+ TEST_REL_INT(0, ==, DNS_int_ParseResponse(test_packet_1, sizeof(test_packet_1), &stage, test_response_parse_1_cb) );
+ return 0;
+}
+
+int main(void)
+{
+ int rv = 0;
+ // - Name Encode
+ // - Name Decode
+ // - Response parsing
+ rv |= test_response_parse_1();
+ return rv;
+}
#include <stdint.h> // uint*_t
#include <string.h> // memcpy, strchr
#include <assert.h>
+#include <acess/sys.h> // for _SysSelect
+#include <acess/fd_set.h> // FD_SET
#include <net.h>
#include "include/dns.h"
// === PROTOTYPES ===
+//int DNS_Query(int ServerAType, const void *ServerAddr, const char *name, enum eTypes type, enum eClass class, handle_record_t* handle_record, void *info);
+int DNS_int_ParseResponse(const void* packet, size_t return_len, void *info, handle_record_t* handle_record_t);
size_t DNS_EncodeName(void *buf, const char *dotted_name);
-int DNS_DecodeName(char dotted_name[256], const void *buf, size_t space);
-int DNS_int_ParseRR(const void *buf, size_t space, char* name_p, enum eTypes* type_p, enum eClass* class_p, uint32_t* ttl_p, size_t* rdlength_p);
+int DNS_DecodeName(char dotted_name[256], const void *buf, size_t ofs, size_t space);
+int DNS_int_ParseRR(const void *buf, size_t ofs, size_t space, char* name_p, enum eTypes* type_p, enum eClass* class_p, uint32_t* ttl_p, size_t* rdlength_p);
+
static uint16_t get16(const void *buf);
+static uint32_t get32(const void *buf);
static size_t put16(void *buf, uint16_t val);
int sock = Net_OpenSocket_UDP(ServerAType, ServerAddr, 53, 0);
if( sock < 0 ) {
// Connection failed
+ _SysDebug("DNS_Query - UDP open failed");
// TODO: Correctly report this failure with a useful error code
return 1;
}
- int rv = _SysWrite(sock, packet, pos);
+ int rv = Net_UDP_SendTo(sock, 53, ServerAType, ServerAddr, pos, packet);
if( rv != pos ) {
+ _SysDebug("DNS_Query - Write failed");
// TODO: Error reporting
_SysClose(sock);
return 1;
}
// - Wait
- int return_len = 0;
- do {
- return_len = _SysRead(sock, packet, sizeof(packet));
- } while( return_len == 0 );
- if( return_len < 0 ) {
+ {
+ int nfd = sock + 1;
+ fd_set fds;
+ FD_ZERO(&fds);
+ FD_SET(sock, &fds);
+ int64_t timeout = 2000; // Give it two seconds, should be long enough
+ rv = _SysSelect(nfd, &fds, NULL, NULL, &timeout, 0);
+ if( rv == 0 ) {
+ // Timeout with no reply, give up
+ _SysDebug("DNS_Query - Timeout");
+ _SysClose(sock);
+ return 1;
+ }
+ if( rv < 0 ) {
+ // Oops, select failed
+ _SysDebug("DNS_Query - Select failure");
+ _SysClose(sock);
+ return 1;
+ }
+ }
+ int return_len = Net_UDP_RecvFrom(sock, NULL, NULL, NULL, sizeof(packet), packet);
+ if( return_len <= 0 ) {
// TODO: Error reporting
+ _SysDebug("DNS_Query - Read failure");
_SysClose(sock);
return 1;
}
// > TODO: Lock DNS queries
// For each response in the answer (and additional) sections, call the passed callback
+ return DNS_int_ParseResponse(packet, return_len, info, handle_record);
+}
+
+int DNS_int_ParseResponse(const void* buf, size_t return_len, void *info, handle_record_t* handle_record)
+{
+ const uint8_t* packet = buf;
char rr_name[256];
+ unsigned int id = get16(packet + 0);
+ if( id != 0xAC00 ) {
+ _SysDebug("DNS_Query - Packet ID mismatch");
+ return 2;
+ }
+ unsigned int flags = get16(packet + 2);
unsigned int qd_count = get16(packet + 4);
unsigned int an_count = get16(packet + 6);
unsigned int ns_count = get16(packet + 8);
unsigned int ar_count = get16(packet + 10);
- pos = 6*2;
+ size_t pos = 6*2;
// TODO: Can I safely assert / fail if qd_count is non-zero?
// - Questions, ignored
for( unsigned int i = 0; i < qd_count; i ++ ) {
- pos += DNS_DecodeName(NULL, packet + pos, return_len - pos);
- pos += 2*2;
+ int rv = DNS_DecodeName(rr_name, packet, pos, return_len);
+ if( rv < 0 ) {
+ _SysDebug("DNS_Query - Parse error in QD");
+ return 1;
+ }
+ pos += rv + 2*2;
}
// - Answers, pass on to handler
for( unsigned int i = 0; i < an_count; i ++ )
enum eClass class;
uint32_t ttl;
size_t rdlength;
- int rv = DNS_int_ParseRR(packet + pos, return_len - pos, rr_name, &type, &class, &ttl, &rdlength);
+ int rv = DNS_int_ParseRR(packet, pos, return_len, rr_name, &type, &class, &ttl, &rdlength);
if( rv < 0 ) {
+ _SysDebug("DNS_Query - Parse error in AN");
return 1;
}
pos += rv;
- handle_record(info, rr_name, type, class, ttl, rdlength, packet + pos);
+ handle_record(info, rr_name, type, class, ttl, rdlength, packet + pos - rdlength);
}
// Authority Records (should all be NS records)
for( unsigned int i = 0; i < ns_count; i ++ )
{
size_t rdlength;
- int rv = DNS_int_ParseRR(packet + pos, return_len - pos, rr_name, NULL, NULL, NULL, &rdlength);
+ int rv = DNS_int_ParseRR(packet, pos, return_len, rr_name, NULL, NULL, NULL, &rdlength);
if( rv < 0 ) {
+ _SysDebug("DNS_Query - Parse error in NS");
return 1;
}
pos += rv;
enum eClass class;
uint32_t ttl;
size_t rdlength;
- int rv = DNS_int_ParseRR(packet + pos, return_len - pos, rr_name, &type, &class, &ttl, &rdlength);
+ int rv = DNS_int_ParseRR(packet, pos, return_len, rr_name, &type, &class, &ttl, &rdlength);
if( rv < 0 ) {
+ _SysDebug("DNS_Query - Parse error in AR");
return 1;
}
pos += rv;
- handle_record(info, rr_name, type, class, ttl, rdlength, packet + pos);
+ handle_record(info, rr_name, type, class, ttl, rdlength, packet + pos - rdlength);
}
-
+
return 0;
}
}
// Decode a name (including trailing . for root)
-int DNS_DecodeName(char dotted_name[256], const void *buf, size_t space)
+int DNS_DecodeName(char dotted_name[256], const void *buf, size_t ofs, size_t space)
{
int consumed = 0;
int out_pos = 0;
- const uint8_t *buf8 = buf;
- while( *buf8 && space > 0 )
+ const uint8_t *buf8 = (const uint8_t*)buf + ofs;
+ for( ;; )
{
- if( consumed + 1 > space ) return -1;
+ if( ofs + consumed + 1 > space ) {
+ _SysDebug("DNS_DecodeName - Len byte OOR space=%i", space);
+ return -1;
+ }
uint8_t seg_len = *buf8;
buf8 ++;
consumed ++;
- // Protocol violation (overflowed end of buffer)
- if( consumed + seg_len > space )
- return -1;
+ // Done
+ if( seg_len == 0 )
+ break;
+ if( (seg_len & 0xC0) == 0xC0 )
+ {
+ // Backreference, the rest of the name is a backref
+ char tmp[256];
+ int ref_ofs = get16(buf8 - 1) & 0x3FFF;
+ consumed += 1, buf8 += 1; // Only one, previous inc still applies
+ _SysDebug("DNS_DecodeName - Nested at %i", ref_ofs);
+ if( DNS_DecodeName(tmp, buf, ref_ofs, space) < 0 )
+ return -1;
+ memcpy(dotted_name+out_pos, tmp, strlen(tmp));
+ out_pos += strlen(tmp);
+ break;
+ }
// Protocol violation (segment too long)
- if( seg_len >= 64 )
+ if( seg_len >= 64 ) {
+ _SysDebug("DNS_DecodeName - Seg too long %i", seg_len);
return -1;
+ }
+ // Protocol violation (overflowed end of buffer)
+ if( ofs + consumed + seg_len > space ) {
+ _SysDebug("DNS_DecodeName - Seg OOR %i+%i>%i", consumed, seg_len, space);
+ return -1;
+ }
// Protocol violation (name was too long)
- if( out_pos + seg_len + 1 > sizeof(dotted_name)-1 )
+ if( out_pos + seg_len + 1 > 255 ) {
+ _SysDebug("DNS_DecodeName - Dotted name too long %i+%i+1 > %i",
+ out_pos, seg_len, 255);
return -1;
+ }
+
+ _SysDebug("DNS_DecodeName : Seg %i '%.*s'", seg_len, seg_len, buf8);
// Read segment
memcpy(dotted_name + out_pos, buf8, seg_len);
buf8 += seg_len;
consumed += seg_len;
+ out_pos += seg_len;
// Place '.'
- dotted_name[out_pos+seg_len+1] = '.';
- // Increment output counter
- out_pos += seg_len + 1;
+ dotted_name[out_pos] = '.';
+ out_pos ++;
}
-
dotted_name[out_pos] = '\0';
+ _SysDebug("DNS_DecodeName - '%s', consumed = %i", dotted_name, consumed);
return consumed;
}
// Parse a Resource Record
-int DNS_int_ParseRR(const void *buf, size_t space, char* name_p, enum eTypes* type_p, enum eClass* class_p, uint32_t* ttl_p, size_t* rdlength_p)
+int DNS_int_ParseRR(const void *buf, size_t ofs, size_t space, char* name_p, enum eTypes* type_p, enum eClass* class_p, uint32_t* ttl_p, size_t* rdlength_p)
{
const uint8_t *buf8 = buf;
size_t consumed = 0;
// 1. Name
- int rv = DNS_DecodeName(name_p, buf8, space);
+ int rv = DNS_DecodeName(name_p, buf, ofs, space);
if(rv < 0) return -1;
- buf8 += rv, consumed += rv;
+ ofs += rv, consumed += rv;
if( type_p )
- *type_p = get16(buf8);
- buf8 += 2, consumed += 2;
+ *type_p = get16(buf8 + ofs);
+ ofs += 2, consumed += 2;
if( class_p )
- *class_p = get16(buf8);
- buf8 += 2, consumed += 2;
+ *class_p = get16(buf8 + ofs);
+ ofs += 2, consumed += 2;
- return consumed;
+ if( ttl_p )
+ *ttl_p = get32(buf + ofs);
+ ofs += 4, consumed += 4;
+
+ size_t rdlength = get16(buf + ofs);
+ if( rdlength_p )
+ *rdlength_p = rdlength;
+ ofs += 2, consumed += 2;
+
+ _SysDebug("DNS_int_ParseRR - name='%s', rdlength=%i", name_p, rdlength);
+
+ return consumed + rdlength;
}
static uint16_t get16(const void *buf) {
const uint8_t* buf8 = buf;
uint16_t rv = 0;
- rv |= buf8[0];
- rv |= (uint16_t)buf8[1] << 8;
+ rv |= (uint16_t)buf8[0] << 8;
+ rv |= (uint16_t)buf8[1] << 0;
+ return rv;
+}
+static uint32_t get32(const void *buf) {
+ const uint8_t* buf8 = buf;
+ uint32_t rv = 0;
+ rv |= (uint32_t)buf8[0] << 24;
+ rv |= (uint32_t)buf8[1] << 16;
+ rv |= (uint32_t)buf8[2] << 8;
+ rv |= (uint32_t)buf8[3] << 0;
return rv;
}
static size_t put16(void *buf, uint16_t val) {
uint8_t* buf8 = buf;
- buf8[0] = val & 0xFF;
- buf8[1] = val >> 8;
+ buf8[0] = val >> 8;
+ buf8[1] = val & 0xFF;
return 2;
}
#include <net.h>
#include "include/dns.h"
#include <string.h>
+#include <stdlib.h> // malloc (for loading config)
#include <stdbool.h>
+#include <acess/sys.h> // _SysDebug
// === TYPES ===
struct sDNSServer
int Net_Lookup_Addrs(const char *Name, void *cb_info, tNet_LookupAddrs_Callback *callback)
{
+ _SysDebug("Net_Lookup_Addrs(Name='%s')", Name);
// 1. Load (if not loaded) the DNS config from "/Acess/Conf/dns"
// - "* <ip> <ip>" for DNS server(s)
// - "127.0.0.1 localhost localhost.localdomain"
+ if( !gaDNSServers )
+ {
+ giNumDNSServers = 1;
+ gaDNSServers = malloc( 1 * sizeof(gaDNSServers[0]) );
+ gaDNSServers[0].AddrType = Net_ParseAddress("192.168.1.1", gaDNSServers[0].AddrData);
+ }
// 2. Check the hosts list
for( int i = 0; i < giNumHostEntries; i ++ )
void int_DNS_callback(void *info_v, const char *name, enum eTypes type, enum eClass class, unsigned int ttl, size_t rdlength, const void *rdata)
{
struct sDNSCallbackInfo *info = info_v;
+ _SysDebug("int_DNS_callback(name='%s', type=%i, class=%i)", name, type, class);
// Check type matches (if pattern was provided)
if( info->desired_type != QTYPE_STAR && type != info->desired_type )
enum eClass
{
- CLASS_IN,
- CLASS_CH, // "Chaos"
+ CLASS_IN = 1,
+ CLASS_CH = 3, // "Chaos"
QCLASS_STAR = 255,
};
#ifndef __LIBNET_H_
#define __LIBNET_H_
+#include <stddef.h>
+
enum {
NET_ADDRTYPE_NULL = 0,
NET_ADDRTYPE_IPV4 = 4,
extern int Net_OpenSocket_TCPC(int AddrType, const void *Addr, int Port);
extern int Net_OpenSocket_UDP(int AddrType, const void *Addr, int RAddr, int LAddr);
+extern int Net_UDP_SendTo (int FD, int Port, int AddrType, const void *Addr, size_t Length, const void *Data);
+extern int Net_UDP_RecvFrom(int FD, int* Port, int* AddrType, void *Addr, size_t Length, void *Data);
/**
#include <net.h>
#include <stdio.h>
#include <stdint.h>
+#include <string.h> // memcpy
#include <acess/sys.h>
enum {
UDP_IOCTL_GETSETRPORT,
UDP_IOCTL_GETSETRMASK,
UDP_IOCTL_SETRADDR,
+ UDP_IOCTL_SENDTO,
+ UDP_IOCTL_RECVFROM,
};
int Net_OpenSocket(int AddrType, const void *Addr, const char *Filename)
int fd = Net_OpenSocket(AddrType, Addr, "tcpc");
if( fd == -1 ) return -1;
- _SysIOCtl(fd, 5, &Port); // Remote Port
- _SysIOCtl(fd, 6, (void*)Addr); // Remote address (kernel shouldn't modify)
- _SysIOCtl(fd, 7, NULL); // connect
+ if( _SysIOCtl(fd, 5, &Port) < 0 ) // Remote Port
+ goto err;
+ if( _SysIOCtl(fd, 6, (void*)Addr) < 0 ) // Remote address (kernel shouldn't modify)
+ goto err;
+ if( _SysIOCtl(fd, 7, NULL) < 0) // connect
+ goto err;
return fd;
+err:
+ _SysClose(fd);
+ return -1;
}
int Net_OpenSocket_UDP(int AddrType, const void *Addr, int RPort, int LPort)
int fd = Net_OpenSocket(AddrType, Addr, "udp");
if( fd == -1 ) return -1;
- _SysIOCtl(fd, UDP_IOCTL_GETSETLPORT, &LPort); // Remote Port
+ if( _SysIOCtl(fd, UDP_IOCTL_GETSETLPORT, &LPort) < 0 )
+ goto err;
+ if( _SysIOCtl(fd, UDP_IOCTL_GETSETRPORT, &RPort) < 0 )
+ goto err;
int maskbits = Net_GetAddressSize(AddrType) * 8;
- _SysIOCtl(fd, UDP_IOCTL_GETSETRPORT, &RPort);
- _SysIOCtl(fd, UDP_IOCTL_GETSETRMASK, &maskbits);
- _SysIOCtl(fd, UDP_IOCTL_SETRADDR, (void*)Addr); // Remote address (kernel shouldn't modify)
+ if( _SysIOCtl(fd, UDP_IOCTL_GETSETRMASK, &maskbits) < 0 )
+ goto err;
+ if( _SysIOCtl(fd, UDP_IOCTL_SETRADDR, (void*)Addr) < 0 ) // Remote address (kernel shouldn't modify)
+ goto err;
return fd;
+err:
+ _SysClose(fd);
+ return -1;
+}
+
+int Net_UDP_SendTo(int FD, int Port, int AddrType, const void *Addr, size_t Length, const void *Data)
+{
+ struct {
+ uint16_t port;
+ uint16_t addr_type;
+ char addr[16];
+ } ep;
+ ep.port = Port;
+ ep.addr_type = AddrType;
+ memcpy(ep.addr, Addr, Net_GetAddressSize(AddrType));
+ struct {
+ const void *ep;
+ const void *buf;
+ uint16_t len;
+ } info = { .ep = &ep, .buf = Data, .len = Length };
+
+ return _SysIOCtl(FD, UDP_IOCTL_SENDTO, &info);
+}
+
+int Net_UDP_RecvFrom(int FD, int* Port, int* AddrType, void *Addr, size_t Length, void *Data)
+{
+ struct {
+ uint16_t port;
+ uint16_t addr_type;
+ char addr[16];
+ } ep;
+ struct {
+ void *ep;
+ void *buf;
+ uint16_t len;
+ } info = { .ep = &ep, .buf = Data, .len = Length };
+
+ int rv = _SysIOCtl(FD, UDP_IOCTL_RECVFROM, &info);
+ if( rv > 0 )
+ {
+ if(Port) *Port = ep.port;
+ if(AddrType) *AddrType = ep.addr_type;
+ if(Addr) memcpy(Addr, ep.addr, Net_GetAddressSize(ep.addr_type));
+ }
+ return rv;
}