summaryrefslogtreecommitdiff
path: root/src/dnsstub/dns_packet.c
diff options
context:
space:
mode:
authorJannis Hoffmann <jannis@fehcom.de>2024-09-28 17:13:21 +0200
committerJannis Hoffmann <jannis@fehcom.de>2024-09-28 17:13:21 +0200
commit4ab19268268cd96b9706625d42a16d2a629134eb (patch)
tree0894a92709675955abb1b15647e8fe2911d89c7f /src/dnsstub/dns_packet.c
parent96cf8dffe4f7b0b910f790066ae622dc429eb522 (diff)
update to version 25
Diffstat (limited to 'src/dnsstub/dns_packet.c')
-rw-r--r--src/dnsstub/dns_packet.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/src/dnsstub/dns_packet.c b/src/dnsstub/dns_packet.c
new file mode 100644
index 0000000..b131635
--- /dev/null
+++ b/src/dnsstub/dns_packet.c
@@ -0,0 +1,85 @@
+#include "error.h"
+#include "dnsresolv.h"
+
+/**
+ * @file dns_packet.c
+ * @author djb
+ * @ref ucspi-tcp
+ * @brief DNS low level packet routine
+ * @brief DNS should have used LZ77 instead of its own sophomoric compression algorithm.
+ */
+
+unsigned int dns_packet_copy(const char *buf,unsigned int len,unsigned int pos,char *out,unsigned int outlen)
+{
+ while (outlen) {
+ if (pos >= len) { errno = EPROTO; return 0; }
+ *out = buf[pos++];
+ ++out; --outlen;
+ }
+ return pos;
+}
+
+unsigned int dns_packet_skipname(const char *buf,unsigned int len,unsigned int pos)
+{
+ unsigned char ch;
+
+ for (;;) {
+ if (pos >= len) break;
+ ch = buf[pos++];
+ if (ch >= 192) return pos + 1;
+ if (ch >= 64) break;
+ if (!ch) return pos;
+ pos += ch;
+ }
+
+ errno = EPROTO;
+ return 0;
+}
+
+unsigned int dns_packet_getname(const char *buf,unsigned int len,unsigned int pos,char **d)
+{
+ unsigned int loop = 0;
+ unsigned int state = 0;
+ unsigned int firstcompress = 0;
+ unsigned int where;
+ unsigned char ch;
+ char name[255];
+ unsigned int namelen = 0;
+
+ for (;;) {
+ if (pos >= len) goto PROTO;
+ ch = buf[pos++];
+ if (++loop >= 1000) goto PROTO;
+
+ if (state) {
+ if (namelen + 1 > sizeof(name)) goto PROTO;
+ name[namelen++] = ch;
+ --state;
+ } else {
+ while (ch >= 192) {
+ where = ch; where -= 192; where <<= 8;
+ if (pos >= len) goto PROTO;
+ ch = buf[pos++];
+ if (!firstcompress) firstcompress = pos;
+ pos = where + ch;
+ if (pos >= len) goto PROTO;
+ ch = buf[pos++];
+ if (++loop >= 1000) goto PROTO;
+ }
+ if (ch >= 64) goto PROTO;
+ if (namelen + 1 > sizeof(name)) goto PROTO;
+ name[namelen++] = ch;
+ if (!ch) break;
+ state = ch;
+ }
+ }
+
+ if (!dns_domain_copy(d,name)) return 0;
+
+ if (firstcompress) return firstcompress;
+ return pos;
+
+ PROTO:
+ errno = EPROTO;
+ return 0;
+}