ohmu
·
2026-10-15
1#include "common/printing.h"
2#include "common/jsonconfig.h"
3#include "common/strutil.h"
4#include "detection/dns/dns.h"
5#include "modules/dns/dns.h"
6
7bool ffPrintDNS(FFDNSOptions* options) {
8 FF_LIST_AUTO_DESTROY result = ffListCreate();
9
10 const char* error = ffDetectDNS(options, &result);
11
12 if (error) {
13 ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DNS), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
14 return false;
15 }
16
17 if (result.length == 0) {
18 ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DNS), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "NO DNS servers detected");
19 return false;
20 }
21
22 FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate();
23 FF_LIST_FOR_EACH (FFstrbuf, item, result) {
24 if (!ffStrbufContainC(item, '.')) {
25 continue; // IPv4
26 }
27 if (buf.length) {
28 ffStrbufAppendC(&buf, ' ');
29 }
30 ffStrbufAppend(&buf, item);
31 }
32 FF_LIST_FOR_EACH (FFstrbuf, item, result) {
33 if (!ffStrbufContainC(item, ':')) {
34 continue; // IPv6
35 }
36 if (buf.length) {
37 ffStrbufAppendC(&buf, ' ');
38 }
39 ffStrbufAppend(&buf, item);
40 }
41
42 if (options->moduleArgs.outputFormat.length == 0) {
43 ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(DNS), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
44
45 ffStrbufPutTo(&buf, stdout);
46 } else {
47 FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(DNS), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) {
48 FF_ARG(buf, "result"),
49 }));
50 }
51
52 FF_LIST_FOR_EACH (FFstrbuf, item, result) {
53 ffStrbufDestroy(item);
54 }
55
56 return true;
57}
58
59void ffParseDNSJsonObject(FFDNSOptions* options, yyjson_val* module) {
60 yyjson_val *key, *val;
61 size_t idx, max;
62 yyjson_obj_foreach (module, idx, max, key, val) {
63 if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) {
64 continue;
65 }
66
67 if (unsafe_yyjson_equals_str(key, "showType")) {
68 int value;
69 const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) {
70 { "both", FF_DNS_TYPE_BOTH },
71 { "ipv4", FF_DNS_TYPE_IPV4_BIT },
72 { "ipv6", FF_DNS_TYPE_IPV6_BIT },
73 {},
74 });
75 if (error) {
76 ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DNS), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error);
77 } else {
78 options->showType = (FFDNSShowType) value;
79 }
80 continue;
81 }
82
83 ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DNS), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
84 }
85}
86
87[[gnu::cold]]
88void ffGenerateDNSJsonConfig(FFDNSOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) {
89 ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs);
90
91 switch ((uint8_t) options->showType) {
92 case FF_DNS_TYPE_IPV4_BIT:
93 yyjson_mut_obj_add_str(doc, module, "showType", "ipv4");
94 break;
95 case FF_DNS_TYPE_IPV6_BIT:
96 yyjson_mut_obj_add_str(doc, module, "showType", "ipv6");
97 break;
98 case FF_DNS_TYPE_BOTH:
99 yyjson_mut_obj_add_str(doc, module, "showType", "both");
100 break;
101 }
102}
103
104bool ffGenerateDNSJsonResult(FFDNSOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) {
105 FF_LIST_AUTO_DESTROY result = ffListCreate();
106
107 const char* error = ffDetectDNS(options, &result);
108
109 if (error) {
110 yyjson_mut_obj_add_str(doc, module, "error", error);
111 return false;
112 }
113
114 yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
115
116 FF_LIST_FOR_EACH (FFstrbuf, item, result) {
117 yyjson_mut_arr_add_strbuf(doc, arr, item);
118 }
119
120 FF_LIST_FOR_EACH (FFstrbuf, item, result) {
121 ffStrbufDestroy(item);
122 }
123
124 return true;
125}
126
127void ffInitDNSOptions(FFDNSOptions* options) {
128 ffOptionInitModuleArg(&options->moduleArgs, "");
129
130 options->showType = FF_DNS_TYPE_BOTH;
131}
132
133void ffDestroyDNSOptions(FFDNSOptions* options) {
134 ffOptionDestroyModuleArg(&options->moduleArgs);
135}
136
137FFModuleBaseInfo ffDNSModuleInfo = {
138 .name = "DNS",
139 .description = "Print configured DNS servers",
140 .displayName = {
141 .en = "DNS",
142 .ar = "DNS",
143 .cs = "DNS",
144 .de = "DNS",
145 .es = "DNS",
146 .fi = "DNS",
147 .fr = "DNS",
148 .gl = "DNS",
149 .he = "DNS",
150 .id = "DNS",
151 .it = "DNS",
152 .ja = "DNS",
153 .ko = "DNS",
154 .pl = "DNS",
155 .pt = "DNS",
156 .ru = "DNS",
157 .tr = "DNS",
158 .uk = "DNS",
159 .vi = "DNS",
160 .zh_CN = "DNS",
161 .zh_TW = "DNS",
162 },
163 .initOptions = (void*) ffInitDNSOptions,
164 .destroyOptions = (void*) ffDestroyDNSOptions,
165 .parseJsonObject = (void*) ffParseDNSJsonObject,
166 .printModule = (void*) ffPrintDNS,
167 .generateJsonResult = (void*) ffGenerateDNSJsonResult,
168 .generateJsonConfig = (void*) ffGenerateDNSJsonConfig,
169 .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) {
170 { "DNS result", "result" },
171 })),
172 .defaultOrder = 51,
173};