]>
git.ipfire.org Git - thirdparty/squid.git/blob - lib/rfc3596.c
5 * Low level DNS protocol routines
6 * AUTHOR: Amos Jeffries, Rafael Martinez Torres
8 * SQUID Web Proxy Cache http://www.squid-cache.org/
9 * ----------------------------------------------------------
11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
20 * This code is copyright (C) 2007 by Treehouse Networks Ltd of
21 * New Zealand. It is published and Lisenced as an extension of
22 * squid under the same conditions as the main squid application.
24 * This program is free software; you can redistribute it and/or modify
25 * it under the terms of the GNU General Public License as published by
26 * the Free Software Foundation; either version 2 of the License, or
27 * (at your option) any later version.
29 * This program is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 * GNU General Public License for more details.
34 * You should have received a copy of the GNU General Public License
35 * along with this program; if not, write to the Free Software
36 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
43 * UDP replies with TC set should be retried via TCP
49 * Provides RFC3596 functions to handle purely IPv6 DNS.
50 * Adds AAAA and IPv6 PTR records.
51 * Other IPv6 records are not mentioned by this RFC.
53 * IPv4 equivalents are taken care of by the RFC1035 library.
54 * Where one protocol lookup must be followed by another, the caller
55 * is resposible for the order and handling of the lookups.
75 #include <sys/types.h>
81 #include <netinet/in.h>
89 #ifndef SQUID_RFC1035_H
90 #error RFC3596 Library depends on RFC1035
94 * Builds a message buffer with a QUESTION to lookup records
95 * for a hostname. Caller must allocate 'buf' which should
96 * probably be at least 512 octets. The 'szp' initially
97 * specifies the size of the buffer, on return it contains
98 * the size of the message (i.e. how much to write).
99 * Returns the size of the query
102 rfc3596BuildHostQuery(const char *hostname
, char *buf
, size_t sz
, unsigned short qid
, rfc1035_query
* query
, int qtype
)
104 static rfc1035_message h
;
106 memset(&h
, '\0', sizeof(h
));
110 h
.opcode
= 0; /* QUERY */
111 h
.qdcount
= (unsigned int) 1;
112 offset
+= rfc1035HeaderPack(buf
+ offset
, sz
- offset
, &h
);
113 offset
+= rfc1035QuestionPack(buf
+ offset
,
120 query
->qtype
= qtype
;
121 query
->qclass
= RFC1035_CLASS_IN
;
122 xstrncpy(query
->name
, hostname
, sizeof(query
->name
));
125 assert(offset
<= sz
);
130 * Builds a message buffer with a QUESTION to lookup A records
131 * for a hostname. Caller must allocate 'buf' which should
132 * probably be at least 512 octets. The 'szp' initially
133 * specifies the size of the buffer, on return it contains
134 * the size of the message (i.e. how much to write).
135 * \return the size of the query
138 rfc3596BuildAQuery(const char *hostname
, char *buf
, size_t sz
, unsigned short qid
, rfc1035_query
* query
)
140 return rfc3596BuildHostQuery(hostname
, buf
, sz
, qid
, query
, RFC1035_TYPE_A
);
144 * Builds a message buffer with a QUESTION to lookup AAAA records
145 * for a hostname. Caller must allocate 'buf' which should
146 * probably be at least 512 octets. The 'szp' initially
147 * specifies the size of the buffer, on return it contains
148 * the size of the message (i.e. how much to write).
149 * \return the size of the query
152 rfc3596BuildAAAAQuery(const char *hostname
, char *buf
, size_t sz
, unsigned short qid
, rfc1035_query
* query
)
154 return rfc3596BuildHostQuery(hostname
, buf
, sz
, qid
, query
, RFC1035_TYPE_AAAA
);
159 * Builds a message buffer with a QUESTION to lookup PTR records
160 * for an address. Caller must allocate 'buf' which should
161 * probably be at least 512 octets. The 'szp' initially
162 * specifies the size of the buffer, on return it contains
163 * the size of the message (i.e. how much to write).
164 * \return the size of the query
168 rfc3596BuildPTRQuery4(const struct in_addr addr
, char *buf
, size_t sz
, unsigned short qid
, rfc1035_query
* query
)
170 static char rev
[RFC1035_MAXHOSTNAMESZ
];
173 i
= (unsigned int) ntohl(addr
.s_addr
);
174 snprintf(rev
, RFC1035_MAXHOSTNAMESZ
, "%u.%u.%u.%u.in-addr.arpa.",
180 return rfc3596BuildHostQuery(rev
, buf
, sz
, qid
, query
, RFC1035_TYPE_PTR
);
185 rfc3596BuildPTRQuery6(const struct in6_addr addr
, char *buf
, size_t sz
, unsigned short qid
, rfc1035_query
* query
)
187 static char rev
[RFC1035_MAXHOSTNAMESZ
];
188 const uint8_t* r
= addr
.s6_addr
;
190 int i
; // NP: MUST allow signed for loop termination.
192 /* work from the raw addr field. anything else may have representation changes. */
193 /* The sin6_port and sin6_addr members shall be in network byte order. */
194 for (i
= 15; i
>= 0; i
--, p
+=4) {
195 snprintf(p
, 5, "%1x.%1x.", ((r
[i
]>>4)&0xf), (r
[i
])&0xf );
198 snprintf(p
,10,"ip6.arpa.");
200 return rfc3596BuildHostQuery(rev
, buf
, sz
, qid
, query
, RFC1035_TYPE_PTR
);
206 /* driver needs the rfc1035 code _without_ the main() */
207 # define main(a,b) rfc1035_main(a,b)
208 # include "rfc1035.c"
211 #include <sys/socket.h>
212 #include <sys/time.h>
215 main(int argc
, char *argv
[])
221 unsigned short sid
, sidb
;
228 if ( argc
< 3 || argc
> 4) {
229 fprintf(stderr
, "usage: %s [-6|-4] ip port\n", argv
[0]);
233 setbuf(stdout
, NULL
);
234 setbuf(stderr
, NULL
);
236 if (argv
[var
][0] == '-') {
237 if (argv
[var
][1] == '4')
239 else if (argv
[var
][1] == '6')
242 fprintf(stderr
, "usage: %s [-6|-4] ip port\n", argv
[0]);
249 s
= socket(PF_INET
, SOCK_DGRAM
, 0);
257 memset(&S
, '\0', sizeof(S
));
260 S
= (struct sockaddr
*) new sockaddr_in6
;
261 memset(S
,0,sizeof(struct sockaddr_in6
));
263 ((struct sockaddr_in6
*)S
)->sin6_family
= AF_INET6
;
264 ((struct sockaddr_in6
*)S
)->sin6_port
= htons(atoi(argv
[var
+1]));
266 if ( ! xinet_pton(AF_INET6
, argv
[var
], &((struct sockaddr_in6
*)S
)->sin6_addr
.s_addr
) )
267 perror("listen address");
271 s
= socket(PF_INET6
, SOCK_DGRAM
, 0);
275 S
= (struct sockaddr
*) new sockaddr_in
;
276 memset(S
,0,sizeof(struct sockaddr_in
));
278 ((struct sockaddr_in
*)S
)->sin_family
= AF_INET
;
279 ((struct sockaddr_in
*)S
)->sin_port
= htons(atoi(argv
[var
+1]));
281 if ( ! xinet_pton(AF_INET
, argv
[var
], &((struct sockaddr_in
*)S
)->sin_addr
.s_addr
) )
282 perror("listen address");
287 while (fgets(input
, 512, stdin
))
290 struct in6_addr junk6
;
292 struct in_addr junk4
;
293 strtok(input
, "\r\n");
294 memset(buf
, '\0', 512);
297 if (xinet_pton(AF_INET6
, input
, &junk6
)) {
298 sid
= rfc1035BuildPTRQuery6(junk6
, buf
, &sz
);
300 } else if (xinet_pton(AF_INET
, input
, &junk4
)) {
301 sid
= rfc1035BuildPTRQuery4(junk4
, buf
, &sz
);
304 sid
= rfc1035BuildAAAAQuery(input
, buf
, &sz
);
305 sidb
= rfc1035BuildAQuery(input
, buf
, &sz
);
308 sendto(s
, buf
, sz
, 0, S
, sizeof(*S
));
318 rl
= select(s
+ 1, &R
, NULL
, NULL
, &to
);
326 memset(rbuf
, '\0', 512);
327 rl
= recv(s
, rbuf
, 512, 0);
329 unsigned short rid
= 0;
332 rfc1035_rr
*answers
= NULL
;
333 n
= rfc1035AnswersUnpack(rbuf
,
339 printf("ERROR %d\n", rfc1035_errno
);
340 } else if (rid
!= sid
&& rid
!= sidb
) {
341 printf("ERROR, ID mismatch (%#hx, %#hx)\n", sid
, rid
);
342 printf("ERROR, ID mismatch (%#hx, %#hx)\n", sidb
, rid
);
344 printf("%d answers\n", n
);
346 for (i
= 0; i
< n
; i
++) {
347 if (answers
[i
].type
== RFC1035_TYPE_A
) {
351 memcpy(&a
, answers
[i
].rdata
, 4);
352 printf("A\t%d\t%s\n", answers
[i
].ttl
, inet_ntop(AF_INET
,&a
,tmp
,16));
353 } else if (answers
[i
].type
== RFC1035_TYPE_AAAA
) {
356 char tmp
[INET6_ADDRSTRLEN
];
357 memcpy(&a
, answers
[i
].rdata
, 16);
358 printf("AAAA\t%d\t%s\n", answers
[i
].ttl
, inet_ntop(AF_INET6
,&a
,tmp
,sizeof(tmp
)));
359 } else if (answers
[i
].type
== RFC1035_TYPE_PTR
) {
360 char ptr
[RFC1035_MAXHOSTNAMESZ
];
361 strncpy(ptr
, answers
[i
].rdata
, answers
[i
].rdlength
);
362 printf("PTR\t%d\t%s\n", answers
[i
].ttl
, ptr
);
363 } else if (answers
[i
].type
== RFC1035_TYPE_CNAME
) {
364 char ptr
[RFC1035_MAXHOSTNAMESZ
];
365 strncpy(ptr
, answers
[i
].rdata
, answers
[i
].rdlength
);
366 printf("CNAME\t%d\t%s\n", answers
[i
].ttl
, ptr
);
368 fprintf(stderr
, "can't print answer type %d\n",
369 (int) answers
[i
].type
);