2 * netsniff-ng - the packet sniffing beast
3 * Subject to the GPL, version 2.
11 #include "trafgen_l7.h"
12 #include "trafgen_proto.h"
14 static struct proto_field dns_fields
[] = {
15 { .id
= DNS_ID
, .len
= 2, .offset
= 0 },
16 { .id
= DNS_QR
, .len
= 2, .offset
= 2, .shift
= 15, .mask
= 0x8000 },
17 { .id
= DNS_OPCODE
, .len
= 2, .offset
= 2, .shift
= 11, .mask
= 0x7800 },
18 { .id
= DNS_AA
, .len
= 2, .offset
= 2, .shift
= 10, .mask
= 0x0400 },
19 { .id
= DNS_TC
, .len
= 2, .offset
= 2, .shift
= 9, .mask
= 0x0200 },
20 { .id
= DNS_RD
, .len
= 2, .offset
= 2, .shift
= 8, .mask
= 0x0100 },
21 { .id
= DNS_RA
, .len
= 2, .offset
= 2, .shift
= 7, .mask
= 0x80 },
22 { .id
= DNS_ZERO
, .len
= 2, .offset
= 2, .shift
= 4, .mask
= 0x30 },
23 { .id
= DNS_RCODE
, .len
= 2, .offset
= 2, .shift
= 0, .mask
= 0xf },
24 { .id
= DNS_QD_COUNT
, .len
= 2, .offset
= 4, },
25 { .id
= DNS_AN_COUNT
, .len
= 2, .offset
= 6, },
26 { .id
= DNS_NS_COUNT
, .len
= 2, .offset
= 8, },
27 { .id
= DNS_AR_COUNT
, .len
= 2, .offset
= 10, },
30 static struct proto_field dns_query_fields
[] = {
31 { .id
= DNS_QUERY_NAME
, .len
= 0, .offset
= 0 },
32 { .id
= DNS_QUERY_TYPE
, .len
= 2, .offset
= 0 },
33 { .id
= DNS_QUERY_CLASS
, .len
= 2, .offset
= 2 },
36 static void dns_query_header_init(struct proto_hdr
*hdr
)
38 proto_header_fields_add(hdr
, dns_query_fields
, array_size(dns_query_fields
));
41 static void dns_query_header_finish(struct proto_hdr
*hdr
)
43 proto_hdr_field_set_default_string(hdr
, DNS_QUERY_NAME
, "www.netsniff-ng.com");
44 proto_hdr_field_set_default_be16(hdr
, DNS_QUERY_CLASS
, 1);
45 proto_hdr_field_set_default_be16(hdr
, DNS_QUERY_TYPE
, 1);
48 static const struct proto_ops dns_proto_query_ops
= {
49 .header_init
= dns_query_header_init
,
50 .header_finish
= dns_query_header_finish
,
53 static struct proto_field dns_rrecord_fields
[] = {
54 { .id
= DNS_RRECORD_NAME
, .len
= 0, .offset
= 0 },
55 { .id
= DNS_RRECORD_TYPE
, .len
= 2, .offset
= 0 },
56 { .id
= DNS_RRECORD_CLASS
, .len
= 2, .offset
= 2 },
57 { .id
= DNS_RRECORD_TTL
, .len
= 4, .offset
= 4 },
58 { .id
= DNS_RRECORD_LEN
, .len
= 2, .offset
= 8 },
59 { .id
= DNS_RRECORD_DATA
, .len
= 0, .offset
= 10 },
62 static void dns_rrecord_header_init(struct proto_hdr
*hdr
)
64 proto_header_fields_add(hdr
, dns_rrecord_fields
, array_size(dns_rrecord_fields
));
67 static void dns_rrecord_header_finish(struct proto_hdr
*hdr
)
69 struct proto_field
*data
= proto_hdr_field_by_id(hdr
, DNS_RRECORD_DATA
);
71 proto_hdr_field_set_default_be32(hdr
, DNS_RRECORD_TTL
, 1);
72 proto_hdr_field_set_default_be16(hdr
, DNS_RRECORD_CLASS
, 1);
73 proto_hdr_field_set_default_be16(hdr
, DNS_RRECORD_LEN
, data
->len
);
76 static const struct proto_ops dns_proto_rrecord_ops
= {
77 .header_init
= dns_rrecord_header_init
,
78 .header_finish
= dns_rrecord_header_finish
,
81 static void dns_header_init(struct proto_hdr
*hdr
)
83 proto_lower_default_add(hdr
, PROTO_UDP
);
85 proto_header_fields_add(hdr
, dns_fields
, array_size(dns_fields
));
88 static void dns_sort_headers(struct proto_hdr
*hdr
, uint32_t id
, int index
)
92 for (i
= index
; i
< hdr
->sub_headers_count
; i
++) {
93 struct proto_hdr
*sub_hdr
= hdr
->sub_headers
[i
];
95 if (sub_hdr
->id
== id
&& sub_hdr
->index
!= index
) {
96 proto_hdr_move_sub_header(hdr
, sub_hdr
, hdr
->sub_headers
[index
]);
102 static void dns_header_finish(struct proto_hdr
*hdr
)
110 for (i
= 0; i
< hdr
->sub_headers_count
; i
++) {
111 struct proto_hdr
*sub_hdr
= hdr
->sub_headers
[i
];
113 switch (sub_hdr
->id
) {
129 dns_sort_headers(hdr
, DNS_QUERY_HDR
, 0);
130 dns_sort_headers(hdr
, DNS_ANSWER_HDR
, qd_count
);
131 dns_sort_headers(hdr
, DNS_AUTH_HDR
, qd_count
+ an_count
);
132 dns_sort_headers(hdr
, DNS_ADD_HDR
, qd_count
+ an_count
+ ns_count
);
134 proto_hdr_field_set_default_be16(hdr
, DNS_QD_COUNT
, qd_count
);
135 proto_hdr_field_set_default_be16(hdr
, DNS_AN_COUNT
, an_count
);
136 proto_hdr_field_set_default_be16(hdr
, DNS_NS_COUNT
, ns_count
);
137 proto_hdr_field_set_default_be16(hdr
, DNS_AR_COUNT
, ar_count
);
140 proto_hdr_field_set_default_be16(hdr
, DNS_QR
, 1);
143 static void dns_push_sub_header(struct proto_hdr
*hdr
, struct proto_hdr
*sub_hdr
)
145 switch (sub_hdr
->id
) {
147 sub_hdr
->ops
= &dns_proto_query_ops
;
152 sub_hdr
->ops
= &dns_proto_rrecord_ops
;
159 static const struct proto_ops dns_proto_ops
= {
162 .header_init
= dns_header_init
,
163 .header_finish
= dns_header_finish
,
164 .push_sub_header
= dns_push_sub_header
,
167 void protos_l7_init(void)
169 proto_ops_register(&dns_proto_ops
);