]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/dns/rfc3596.cc
720861b6bce3216ad4a26b7fc41b2f5e8ba6476c
2 * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
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.
10 #include "dns/rfc2671.h"
11 #include "dns/rfc3596.h"
24 #include <netinet/in.h>
30 #ifndef SQUID_RFC1035_H
31 #error RFC3596 Library depends on RFC1035
35 * Low level DNS protocol routines
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.
41 * IPv4 equivalents are taken care of by the RFC1035 library.
42 * Where one protocol lookup must be followed by another, the caller
43 * is resposible for the order and handling of the lookups.
47 * UDP replies with TC set should be retried via TCP
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
59 rfc3596BuildHostQuery(const char *hostname
, char *buf
, size_t sz
, unsigned short qid
, rfc1035_query
* query
, int qtype
, ssize_t edns_sz
)
61 static rfc1035_message h
;
63 memset(&h
, '\0', sizeof(h
));
67 h
.opcode
= 0; /* QUERY */
68 h
.qdcount
= (unsigned int) 1;
69 h
.arcount
= (edns_sz
> 0 ? 1 : 0);
70 offset
+= rfc1035HeaderPack(buf
+ offset
, sz
- offset
, &h
);
71 offset
+= rfc1035QuestionPack(buf
+ offset
,
77 offset
+= rfc2671RROptPack(buf
+ offset
, sz
- offset
, edns_sz
);
81 query
->qclass
= RFC1035_CLASS_IN
;
82 xstrncpy(query
->name
, hostname
, sizeof(query
->name
));
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
98 rfc3596BuildAQuery(const char *hostname
, char *buf
, size_t sz
, unsigned short qid
, rfc1035_query
* query
, ssize_t edns_sz
)
100 return rfc3596BuildHostQuery(hostname
, buf
, sz
, qid
, query
, RFC1035_TYPE_A
, edns_sz
);
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
112 rfc3596BuildAAAAQuery(const char *hostname
, char *buf
, size_t sz
, unsigned short qid
, rfc1035_query
* query
, ssize_t edns_sz
)
114 return rfc3596BuildHostQuery(hostname
, buf
, sz
, qid
, query
, RFC1035_TYPE_AAAA
, edns_sz
);
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
126 rfc3596BuildPTRQuery4(const struct in_addr addr
, char *buf
, size_t sz
, unsigned short qid
, rfc1035_query
* query
, ssize_t edns_sz
)
128 static char rev
[RFC1035_MAXHOSTNAMESZ
];
131 i
= (unsigned int) ntohl(addr
.s_addr
);
132 snprintf(rev
, RFC1035_MAXHOSTNAMESZ
, "%u.%u.%u.%u.in-addr.arpa.",
138 return rfc3596BuildHostQuery(rev
, buf
, sz
, qid
, query
, RFC1035_TYPE_PTR
, edns_sz
);
142 rfc3596BuildPTRQuery6(const struct in6_addr addr
, char *buf
, size_t sz
, unsigned short qid
, rfc1035_query
* query
, ssize_t edns_sz
)
144 static char rev
[RFC1035_MAXHOSTNAMESZ
];
145 const uint8_t* r
= addr
.s6_addr
;
147 int i
; /* NP: MUST allow signed for loop termination. */
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. */
151 for (i
= 15; i
>= 0; i
--, p
+=4) {
152 snprintf(p
, 5, "%1x.%1x.", ((r
[i
])&0xf), (r
[i
]>>4)&0xf );
155 snprintf(p
,10,"ip6.arpa.");
157 return rfc3596BuildHostQuery(rev
, buf
, sz
, qid
, query
, RFC1035_TYPE_PTR
, edns_sz
);
162 /* driver needs the rfc1035 code _without_ the main() */
163 # define main(a,b) rfc1035_main(a,b)
164 # include "rfc1035.c"
167 #include <sys/socket.h>
170 main(int argc
, char *argv
[])
172 #define PACKET_BUFSZ 1024
173 char input
[PACKET_BUFSZ
];
174 char buf
[PACKET_BUFSZ
];
175 char rbuf
[PACKET_BUFSZ
];
176 size_t sz
= PACKET_BUFSZ
;
177 unsigned short sid
, sidb
;
180 ssize_t edns_max
= -1;
185 if ( argc
< 3 || argc
> 4) {
186 fprintf(stderr
, "usage: %s [-6|-4] ip port\n", argv
[0]);
190 setbuf(stdout
, NULL
);
191 setbuf(stderr
, NULL
);
193 if (argv
[var
][0] == '-') {
194 if (argv
[var
][1] == '4')
196 else if (argv
[var
][1] == '6')
198 else if (argv
[var
][1] == 'E')
199 edns_max
= atoi(argv
[var
++]);
201 fprintf(stderr
, "usage: %s [-6|-4] [-E packet-size] ip port\n", argv
[0]);
202 fprintf(stderr
, " EDNS packets my be up to %d\n", PACKET_BUFSZ
);
209 s
= socket(PF_INET
, SOCK_DGRAM
, 0);
216 memset(&S
, '\0', sizeof(S
));
219 S
= (struct sockaddr
*) new sockaddr_in6
;
220 memset(S
,0,sizeof(struct sockaddr_in6
));
222 ((struct sockaddr_in6
*)S
)->sin6_family
= AF_INET6
;
223 ((struct sockaddr_in6
*)S
)->sin6_port
= htons(atoi(argv
[var
+1]));
225 if ( ! inet_pton(AF_INET6
, argv
[var
], &((struct sockaddr_in6
*)S
)->sin6_addr
.s_addr
) ) {
226 perror("listen address");
230 s
= socket(PF_INET6
, SOCK_DGRAM
, 0);
232 S
= (struct sockaddr
*) new sockaddr_in
;
233 memset(S
,0,sizeof(struct sockaddr_in
));
235 ((struct sockaddr_in
*)S
)->sin_family
= AF_INET
;
236 ((struct sockaddr_in
*)S
)->sin_port
= htons(atoi(argv
[var
+1]));
238 if ( ! inet_pton(AF_INET
, argv
[var
], &((struct sockaddr_in
*)S
)->sin_addr
.s_addr
) )
239 perror("listen address");
244 while (fgets(input
, PACKET_BUFSZ
, stdin
))
247 struct in6_addr junk6
;
249 struct in_addr junk4
;
250 strtok(input
, "\r\n");
251 memset(buf
, '\0', PACKET_BUFSZ
);
254 if (inet_pton(AF_INET6
, input
, &junk6
)) {
255 sid
= rfc1035BuildPTRQuery6(junk6
, buf
, &sz
, edns_max
);
257 } else if (inet_pton(AF_INET
, input
, &junk4
)) {
258 sid
= rfc1035BuildPTRQuery4(junk4
, buf
, &sz
, edns_max
);
261 sid
= rfc1035BuildAAAAQuery(input
, buf
, &sz
, edns_max
);
262 sidb
= rfc1035BuildAQuery(input
, buf
, &sz
, edns_max
);
265 sendto(s
, buf
, sz
, 0, S
, sizeof(*S
));
275 rl
= select(s
+ 1, &R
, NULL
, NULL
, &to
);
283 memset(rbuf
, '\0', PACKET_BUFSZ
);
284 rl
= recv(s
, rbuf
, PACKET_BUFSZ
, 0);
286 unsigned short rid
= 0;
289 rfc1035_rr
*answers
= NULL
;
290 n
= rfc1035AnswersUnpack(rbuf
,
296 printf("ERROR %d\n", -n
);
297 } else if (rid
!= sid
&& rid
!= sidb
) {
298 printf("ERROR, ID mismatch (%#hx, %#hx)\n", sid
, rid
);
299 printf("ERROR, ID mismatch (%#hx, %#hx)\n", sidb
, rid
);
301 printf("%d answers\n", n
);
303 for (i
= 0; i
< n
; i
++) {
304 if (answers
[i
].type
== RFC1035_TYPE_A
) {
308 memcpy(&a
, answers
[i
].rdata
, 4);
309 printf("A\t%d\t%s\n", answers
[i
].ttl
, inet_ntop(AF_INET
,&a
,tmp
,16));
310 } else if (answers
[i
].type
== RFC1035_TYPE_AAAA
) {
313 char tmp
[INET6_ADDRSTRLEN
];
314 memcpy(&a
, answers
[i
].rdata
, 16);
315 printf("AAAA\t%d\t%s\n", answers
[i
].ttl
, inet_ntop(AF_INET6
,&a
,tmp
,sizeof(tmp
)));
316 } else if (answers
[i
].type
== RFC1035_TYPE_PTR
) {
317 char ptr
[RFC1035_MAXHOSTNAMESZ
];
318 strncpy(ptr
, answers
[i
].rdata
, answers
[i
].rdlength
);
319 printf("PTR\t%d\t%s\n", answers
[i
].ttl
, ptr
);
320 } else if (answers
[i
].type
== RFC1035_TYPE_CNAME
) {
321 char ptr
[RFC1035_MAXHOSTNAMESZ
];
322 strncpy(ptr
, answers
[i
].rdata
, answers
[i
].rdlength
);
323 printf("CNAME\t%d\t%s\n", answers
[i
].ttl
, ptr
);
325 fprintf(stderr
, "can't print answer type %d\n",
326 (int) answers
[i
].type
);