]> git.ipfire.org Git - thirdparty/squid.git/blame - src/dns/rfc3596.cc
Source Format Enforcement (#1234)
[thirdparty/squid.git] / src / dns / rfc3596.cc
CommitLineData
0710cbcd 1/*
b8ae064d 2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
0710cbcd 3 *
0545caaa
AJ
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
0710cbcd 7 */
8
f7f3304a 9#include "squid.h"
4a3b98d7
AJ
10#include "dns/rfc2671.h"
11#include "dns/rfc3596.h"
0710cbcd 12#include "util.h"
13
0710cbcd 14#if HAVE_UNISTD_H
15#include <unistd.h>
16#endif
0710cbcd 17#if HAVE_MEMORY_H
18#include <memory.h>
19#endif
0710cbcd 20#if HAVE_ASSERT_H
21#include <assert.h>
22#endif
23#if HAVE_NETINET_IN_H
24#include <netinet/in.h>
25#endif
26#if HAVE_STRINGS_H
27#include <strings.h>
28#endif
29
0710cbcd 30#ifndef SQUID_RFC1035_H
31#error RFC3596 Library depends on RFC1035
32#endif
33
0545caaa
AJ
34/*
35 * Low level DNS protocol routines
36 *
37 * Provides RFC3596 functions to handle purely IPv6 DNS.
38 * Adds AAAA and IPv6 PTR records.
39 * Other IPv6 records are not mentioned by this RFC.
40 *
41 * IPv4 equivalents are taken care of by the RFC1035 library.
42 * Where one protocol lookup must be followed by another, the caller
2f8abb64 43 * is responsible for the order and handling of the lookups.
0545caaa
AJ
44 *
45 * KNOWN BUGS:
46 *
47 * UDP replies with TC set should be retried via TCP
48 */
49
0710cbcd 50/**
51 * Builds a message buffer with a QUESTION to lookup records
52 * for a hostname. Caller must allocate 'buf' which should
53 * probably be at least 512 octets. The 'szp' initially
54 * specifies the size of the buffer, on return it contains
55 * the size of the message (i.e. how much to write).
56 * Returns the size of the query
57 */
58ssize_t
e210930b 59rfc3596BuildHostQuery(const char *hostname, char *buf, size_t sz, unsigned short qid, rfc1035_query * query, int qtype, ssize_t edns_sz)
0710cbcd 60{
61 static rfc1035_message h;
62 size_t offset = 0;
63 memset(&h, '\0', sizeof(h));
64 h.id = qid;
65 h.qr = 0;
66 h.rd = 1;
67 h.opcode = 0; /* QUERY */
68 h.qdcount = (unsigned int) 1;
e210930b 69 h.arcount = (edns_sz > 0 ? 1 : 0);
0710cbcd 70 offset += rfc1035HeaderPack(buf + offset, sz - offset, &h);
71 offset += rfc1035QuestionPack(buf + offset,
72 sz - offset,
73 hostname,
74 qtype,
75 RFC1035_CLASS_IN);
e210930b
AJ
76 if (edns_sz > 0)
77 offset += rfc2671RROptPack(buf + offset, sz - offset, edns_sz);
0710cbcd 78
79 if (query) {
80 query->qtype = qtype;
81 query->qclass = RFC1035_CLASS_IN;
82 xstrncpy(query->name, hostname, sizeof(query->name));
83 }
84
85 assert(offset <= sz);
86 return offset;
87}
88
89/**
90 * Builds a message buffer with a QUESTION to lookup A records
91 * for a hostname. Caller must allocate 'buf' which should
92 * probably be at least 512 octets. The 'szp' initially
93 * specifies the size of the buffer, on return it contains
94 * the size of the message (i.e. how much to write).
95 * \return the size of the query
96 */
97ssize_t
e210930b 98rfc3596BuildAQuery(const char *hostname, char *buf, size_t sz, unsigned short qid, rfc1035_query * query, ssize_t edns_sz)
0710cbcd 99{
e210930b 100 return rfc3596BuildHostQuery(hostname, buf, sz, qid, query, RFC1035_TYPE_A, edns_sz);
0710cbcd 101}
102
103/**
104 * Builds a message buffer with a QUESTION to lookup AAAA records
105 * for a hostname. Caller must allocate 'buf' which should
106 * probably be at least 512 octets. The 'szp' initially
107 * specifies the size of the buffer, on return it contains
108 * the size of the message (i.e. how much to write).
109 * \return the size of the query
110 */
111ssize_t
e210930b 112rfc3596BuildAAAAQuery(const char *hostname, char *buf, size_t sz, unsigned short qid, rfc1035_query * query, ssize_t edns_sz)
0710cbcd 113{
e210930b 114 return rfc3596BuildHostQuery(hostname, buf, sz, qid, query, RFC1035_TYPE_AAAA, edns_sz);
0710cbcd 115}
116
0710cbcd 117/**
118 * Builds a message buffer with a QUESTION to lookup PTR records
119 * for an address. Caller must allocate 'buf' which should
120 * probably be at least 512 octets. The 'szp' initially
121 * specifies the size of the buffer, on return it contains
122 * the size of the message (i.e. how much to write).
123 * \return the size of the query
124 */
125ssize_t
e210930b 126rfc3596BuildPTRQuery4(const struct in_addr addr, char *buf, size_t sz, unsigned short qid, rfc1035_query * query, ssize_t edns_sz)
0710cbcd 127{
128 static char rev[RFC1035_MAXHOSTNAMESZ];
129 unsigned int i;
130
131 i = (unsigned int) ntohl(addr.s_addr);
132 snprintf(rev, RFC1035_MAXHOSTNAMESZ, "%u.%u.%u.%u.in-addr.arpa.",
133 i & 255,
134 (i >> 8) & 255,
135 (i >> 16) & 255,
136 (i >> 24) & 255);
137
e210930b 138 return rfc3596BuildHostQuery(rev, buf, sz, qid, query, RFC1035_TYPE_PTR, edns_sz);
0710cbcd 139}
140
141ssize_t
e210930b 142rfc3596BuildPTRQuery6(const struct in6_addr addr, char *buf, size_t sz, unsigned short qid, rfc1035_query * query, ssize_t edns_sz)
0710cbcd 143{
144 static char rev[RFC1035_MAXHOSTNAMESZ];
145 const uint8_t* r = addr.s6_addr;
146 char* p = rev;
b8031529 147 int i; /* NP: MUST allow signed for loop termination. */
0710cbcd 148
149 /* work from the raw addr field. anything else may have representation changes. */
150 /* The sin6_port and sin6_addr members shall be in network byte order. */
26ac0430 151 for (i = 15; i >= 0; i--, p+=4) {
5c4e391c 152 snprintf(p, 5, "%1x.%1x.", ((r[i])&0xf), (r[i]>>4)&0xf );
0710cbcd 153 }
154
155 snprintf(p,10,"ip6.arpa.");
156
e210930b 157 return rfc3596BuildHostQuery(rev, buf, sz, qid, query, RFC1035_TYPE_PTR, edns_sz);
0710cbcd 158}
159