document the default privilege drop (Closes #34)
[prads.git] / src / dump_dns.c
blob3fac72abf2dcc8947ce029c24316dea228893fcb
1 /* dump_dns.c - library function to emit decoded dns message on a FILE.
3 */
5 #include <sys/types.h>
6 #include <stdio.h>
7 #include "dump_dns.h"
9 /* Define to 1 if you have the `ns_initparse' function. */
10 #define HAVE_NS_INITPARSE 1
12 /* Define to 1 if you have the `ns_parserr' function. */
13 #define HAVE_NS_PARSERR 1
15 #if HAVE_NS_INITPARSE && HAVE_NS_PARSERR
18 * Copyright (c) 2007 by Internet Systems Consortium, Inc. ("ISC")
20 * Permission to use, copy, modify, and/or distribute this software for any
21 * purpose with or without fee is hereby granted, provided that the above
22 * copyright notice and this permission notice appear in all copies.
24 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
25 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
27 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
28 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
29 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
30 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
33 #ifdef __linux__
34 #define _GNU_SOURCE
35 #ifndef __USE_POSIX199309
36 #define __USE_POSIX199309
37 #endif
38 #endif
40 #ifdef __SVR4
41 #define u_int32_t uint32_t
42 #define u_int16_t uint16_t
43 #endif
45 #include <sys/socket.h>
46 #include <sys/time.h>
48 #include <netinet/in.h>
49 #include <arpa/inet.h>
50 #include <arpa/nameser.h>
52 #include <assert.h>
53 #include <errno.h>
54 #include <fcntl.h>
55 #include <resolv.h>
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <signal.h>
59 #include <string.h>
60 #include <time.h>
61 #include <unistd.h>
63 extern const char *_res_opcodes[];
64 extern const char *_res_sectioncodes[];
65 #ifndef __APPLE__
66 #define p_rcode __p_rcode
67 #endif
68 extern const char *p_rcode(int rcode);
70 static void dump_dns_sect(ns_msg *, ns_sect, FILE *, const char *);
71 static void dump_dns_rr(ns_msg *, ns_rr *, ns_sect, FILE *);
72 void dump_payload(u_char * xdata, uint16_t dlen);
73 char *fasthex(u_char * xdata, u_int16_t length);
74 void printchars(char buf[NS_MAXDNAME], u_char * cdata, u_int16_t dlen);
76 #ifndef INT16SZ
77 #define INT16SZ (2)
78 #endif
79 #ifndef INT32SZ
80 #define INT32SZ (4)
81 #endif
83 #define MY_GET16(s, cp) do { \
84 register const u_char *t_cp = (const u_char *)(cp); \
85 (s) = ((u_int16_t)t_cp[0] << 8) \
86 | ((u_int16_t)t_cp[1]) \
87 ; \
88 (cp) += INT16SZ; \
89 } while (0)
91 #define MY_GET32(l, cp) do { \
92 register const u_char *t_cp = (const u_char *)(cp); \
93 (l) = ((u_int32_t)t_cp[0] << 24) \
94 | ((u_int32_t)t_cp[1] << 16) \
95 | ((u_int32_t)t_cp[2] << 8) \
96 | ((u_int32_t)t_cp[3]) \
97 ; \
98 (cp) += INT32SZ; \
99 } while (0)
101 #ifdef __FreeBSD__
102 const char *_res_opcodes[] = {
103 "QUERY",
104 "IQUERY",
105 "CQUERYM",
106 "CQUERYU", /* experimental */
107 "NOTIFY", /* experimental */
108 "UPDATE",
109 "6",
110 "7",
111 "8",
112 "UPDATEA",
113 "UPDATED",
114 "UPDATEDA",
115 "UPDATEM",
116 "UPDATEMA",
117 "ZONEINIT",
118 "ZONEREF",
120 #endif /* __FreeBSD__ */
122 //#include "dump_dns.h"
124 void
125 dump_dns(const u_char * payload, size_t paylen,
126 FILE * trace, const char *endline, const char *src_ip, time_t ts)
128 u_int opcode, rcode, id;
129 const char *sep;
130 ns_msg msg;
131 const char *host = "host";
133 /*fprintf(trace, "%sdns ", endline); */
134 fprintf(trace, "%ld||%s||%s||", ts, host, src_ip);
135 if(ns_initparse(payload, paylen, &msg) < 0) {
136 fputs(strerror(errno), trace);
137 return;
139 opcode = ns_msg_getflag(msg, ns_f_opcode);
140 rcode = ns_msg_getflag(msg, ns_f_rcode);
141 id = ns_msg_id(msg);
142 fprintf(trace, "%s,%s,%u", _res_opcodes[opcode], p_rcode(rcode), id);
143 sep = ",";
144 #define FLAG(t,f) if (ns_msg_getflag(msg, f)) { \
145 fprintf(trace, "%s%s", sep, t); \
146 sep = "|"; \
148 FLAG("qr", ns_f_qr);
149 FLAG("aa", ns_f_aa);
150 FLAG("tc", ns_f_tc);
151 FLAG("rd", ns_f_rd);
152 FLAG("ra", ns_f_ra);
153 FLAG("z", ns_f_z);
154 FLAG("ad", ns_f_ad);
155 FLAG("cd", ns_f_cd);
156 #undef FLAG
158 //if(ns_o_query == opcode && ns_msg_getflag(msg,ns_f_qr)){
159 // question?
160 dump_dns_sect(&msg, ns_s_qd, trace, endline);
161 // answer?
162 dump_dns_sect(&msg, ns_s_an, trace, endline);
163 // name servers?
164 dump_dns_sect(&msg, ns_s_ns, trace, endline);
165 // additional records?
166 dump_dns_sect(&msg, ns_s_ar, trace, endline);
167 fprintf(trace, "\n");
170 static void
171 dump_dns_sect(ns_msg * msg, ns_sect sect, FILE * trace,
172 const char *endline)
174 int rrnum, rrmax;
175 ns_rr rr;
177 fprintf(trace, "||");
178 rrmax = ns_msg_count(*msg, sect);
179 if(rrmax == 0) {
180 fputs("0", trace);
181 return;
183 fprintf(trace, "%d", rrmax);
184 //fprintf(trace, "%s%d", endline, rrmax);
185 //fprintf(trace, "%s", endline);
186 for(rrnum = 0; rrnum < rrmax; rrnum++) {
187 if(ns_parserr(msg, sect, rrnum, &rr)) {
188 fputs(strerror(errno), trace);
189 return;
191 fprintf(trace, "||");
192 dump_dns_rr(msg, &rr, sect, trace);
196 static void
197 dump_dns_rr(ns_msg * msg, ns_rr * rr, ns_sect sect, FILE * trace)
199 char buf[NS_MAXDNAME];
200 u_int class, type;
201 const u_char *rd;
202 u_int32_t soa[5];
203 u_int16_t mx;
204 int n;
206 class = ns_rr_class(*rr);
207 type = ns_rr_type(*rr);
208 fprintf(trace, "%s,%s,%s",
209 ns_rr_name(*rr), p_class(class), p_type(type));
210 if(sect == ns_s_qd)
211 return;
212 fprintf(trace, ",%lu", (u_long) ns_rr_ttl(*rr));
213 rd = ns_rr_rdata(*rr);
214 switch (type) {
215 case ns_t_soa:
216 n = ns_name_uncompress(ns_msg_base(*msg), ns_msg_end(*msg),
217 rd, buf, sizeof buf);
218 if(n < 0)
219 goto error;
220 putc(',', trace);
221 fputs(buf, trace);
222 rd += n;
223 n = ns_name_uncompress(ns_msg_base(*msg), ns_msg_end(*msg),
224 rd, buf, sizeof buf);
225 if(n < 0)
226 goto error;
227 putc(',', trace);
228 fputs(buf, trace);
229 rd += n;
230 if(ns_msg_end(*msg) - rd < 5 * NS_INT32SZ)
231 goto error;
232 for(n = 0; n < 5; n++)
233 MY_GET32(soa[n], rd);
234 sprintf(buf, "%u,%u,%u,%u,%u", soa[0], soa[1], soa[2], soa[3],
235 soa[4]);
236 break;
237 case ns_t_a:
238 inet_ntop(AF_INET, rd, buf, sizeof buf);
239 break;
240 case ns_t_aaaa:
241 inet_ntop(AF_INET6, rd, buf, sizeof buf);
242 break;
243 case ns_t_mx:
244 MY_GET16(mx, rd);
245 fprintf(trace, ",%u", mx);
246 /* FALLTHROUGH */
247 case ns_t_ns:
248 case ns_t_txt:
249 case ns_t_ptr:
250 case ns_t_cname:
251 n = ns_name_uncompress(ns_msg_base(*msg), ns_msg_end(*msg),
252 rd, buf, sizeof buf);
253 if(n < 0)
254 goto error;
255 break;
256 default:
257 error:
258 sprintf(buf, "[%u]", ns_rr_rdlen(*rr));
259 //fprintf(stderr, ",[%u],", ns_rr_rdlen(*rr));
260 /*fprintf(trace, ",");
261 for (i=1;i<ns_rr_rdlen(*rr);i++) {
262 if ( 31 < rd[i] && rd[i] < 127) {
263 fprintf(trace, "%c", rd[i]);
264 } else {
265 fprintf(trace, ".");
267 } */
269 if(buf[0] != '\0') {
270 putc(',', trace);
271 fputs(buf, trace);
275 void printchars(char buf[NS_MAXDNAME], u_char * cdata, u_int16_t dlen)
277 uint8_t i;
279 printf("[");
280 for(i = 0; i < dlen; i++) {
281 if(31 < cdata[i] && cdata[i] < 127) {
282 printf("%c", cdata[i]);
285 printf("]");
288 #else
290 void
291 dump_dns(const u_char * payload, size_t paylen,
292 FILE * trace, const char *endline)
294 (void) payload;
295 (void) paylen;
296 fprintf(trace, "NO BINDLIB\n");
299 #endif