1 #include <string.h>
2 #include "mmgr.h"
3 #include "stringchunk.h"
4 #include "utils.h"
5 #include "filter.h"
6 #include "hosts.h"
7 #include "dnscache.h"
8 #include "logs.h"
9 #include "ipmisc.h"
10 #include "readline.h"
11
12 typedef int (*SendFunc)(void *Module,
13 IHeader *h, /* Entity followed */
14 int BufferLength
15 );
16
17 typedef struct _ModuleInterface {
18 union {
19 UdpM Udp;
20 TcpM Tcp;
21 } ModuleUnion;
22
23 SendFunc Send;
24
25 const char *ModuleName;
26
27 } ModuleInterface;
28
29 static StableBuffer Modules; /* Storing ModuleInterfaces */
30 static Array ModuleArray; /* ModuleInterfaces' references */
31 static StringChunk Distributor; /* Domain-to-ModuleInterface mapping */
32
MappingAModule(ModuleInterface * Stored,StringList * DomainList)33 static int MappingAModule(ModuleInterface *Stored, StringList *DomainList)
34 {
35 StringListIterator i;
36 const char *OneDomain;
37
38 DomainList->TrimAll(DomainList, "\t .");
39 DomainList->LowercaseAll(DomainList);
40
41 if( StringListIterator_Init(&i, DomainList) != 0 )
42 {
43 return -46;
44 }
45
46 while( (OneDomain = i.Next(&i)) != NULL )
47 {
48 StringChunk_Add_Domain(&Distributor,
49 OneDomain,
50 &Stored,
51 sizeof(ModuleInterface *)
52 );
53 }
54
55 return 0;
56 }
57
StoreAModule(void)58 static ModuleInterface *StoreAModule(void)
59 {
60 ModuleInterface *Added;
61
62 Added = Modules.Add(&Modules, NULL, sizeof(ModuleInterface), TRUE);
63 if( Added == NULL )
64 {
65 return NULL;
66 }
67
68 if( Array_PushBack(&ModuleArray, &Added, NULL) < 0 )
69 {
70 return NULL;
71 }
72
73 Added->ModuleName = "Unknown";
74
75 return Added;
76 }
77
Udp_Init_Core(const char * Services,StringList * DomainList,const char * Parallel)78 static int Udp_Init_Core(const char *Services,
79 StringList *DomainList,
80 const char *Parallel
81 )
82 {
83 ModuleInterface *NewM;
84
85 char ParallelOnOff[8];
86 BOOL ParallelQuery;
87
88 if( Services == NULL || DomainList == NULL || Parallel == NULL )
89 {
90 return -99;
91 }
92
93 NewM = StoreAModule();
94 if( NewM == NULL )
95 {
96 return -101;
97 }
98
99 NewM->ModuleName = "UDP";
100
101 strncpy(ParallelOnOff, Parallel, sizeof(ParallelOnOff));
102 ParallelOnOff[sizeof(ParallelOnOff) - 1] = '\0';
103 StrToLower(ParallelOnOff);
104
105 if( strcmp(ParallelOnOff, "on") == 0 )
106 {
107 ParallelQuery = TRUE;
108 } else {
109 ParallelQuery = FALSE;
110 }
111
112 /* Initializing module */
113 if( UdpM_Init(&(NewM->ModuleUnion.Udp), Services, ParallelQuery) != 0 )
114 {
115 return -128;
116 }
117
118 NewM->Send = (SendFunc)(NewM->ModuleUnion.Udp.Send);
119
120 if( MappingAModule(NewM, DomainList) != 0 )
121 {
122 ERRORMSG("Mapping UDP module of %s failed.\n", Services);
123 }
124
125 return 0;
126 }
127
Udp_Init(StringListIterator * i)128 static int Udp_Init(StringListIterator *i)
129 {
130 const char *Services;
131 const char *Domains;
132 const char *Parallel;
133
134 StringList DomainList;
135
136 /* Initializing parameters */
137 Services = i->Next(i);
138 Domains = i->Next(i);
139 Parallel = i->Next(i);
140
141 if( Domains == NULL )
142 {
143 return -143;
144 }
145
146 if( StringList_Init(&DomainList, Domains, ",") != 0 )
147 {
148 return -148;
149 }
150
151 if( Udp_Init_Core(Services, &DomainList, Parallel) != 0 )
152 {
153 return -153;
154 }
155
156 DomainList.Free(&DomainList);
157
158 return 0;
159 }
160
Tcp_Init_Core(const char * Services,StringList * DomainList,const char * Proxies)161 static int Tcp_Init_Core(const char *Services,
162 StringList *DomainList,
163 const char *Proxies
164 )
165 {
166 ModuleInterface *NewM;
167
168 char ProxyString[8];
169
170 if( Services == NULL || DomainList == NULL || Proxies == NULL )
171 {
172 return -157;
173 }
174
175 NewM = StoreAModule();
176 if( NewM == NULL )
177 {
178 return -192;
179 }
180
181 NewM->ModuleName = "TCP";
182
183 strncpy(ProxyString, Proxies, sizeof(ProxyString));
184 ProxyString[sizeof(ProxyString) - 1] = '\0';
185 StrToLower(ProxyString);
186
187 if( strcmp(ProxyString, "no") == 0 )
188 {
189 Proxies = NULL;
190 }
191
192 /* Initializing module */
193 if( TcpM_Init(&(NewM->ModuleUnion.Tcp), Services, Proxies) != 0 )
194 {
195 return -180;
196 }
197
198 NewM->Send = (SendFunc)(NewM->ModuleUnion.Tcp.Send);
199
200 if( MappingAModule(NewM, DomainList) != 0 )
201 {
202 ERRORMSG("Mapping TCP module of %s failed.\n", Services);
203 }
204
205 return 0;
206 }
207
Tcp_Init(StringListIterator * i)208 static int Tcp_Init(StringListIterator *i)
209 {
210 const char *Services;
211 const char *Domains;
212 const char *Proxies;
213
214 StringList DomainList;
215
216 /* Initializing parameters */
217 Services = i->Next(i);
218 Domains = i->Next(i);
219 Proxies = i->Next(i);
220
221 if( Domains == NULL )
222 {
223 return -143;
224 }
225
226 if( StringList_Init(&DomainList, Domains, ",") != 0 )
227 {
228 return -148;
229 }
230
231 if( Tcp_Init_Core(Services, &DomainList, Proxies) != 0 )
232 {
233 return -233;
234 }
235
236 DomainList.Free(&DomainList);
237
238 return 0;
239 }
240
241 /*
242 # UDP
243 PROTOCOL UDP
244 SERVER 1.2.4.8,127.0.0.1
245 PARALLEL ON
246
247 example.com
248
249 #############################
250 # TCP
251 PROTOCOL TCP
252 SERVER 1.2.4.8,127.0.0.1
253 PROXY NO
254
255 example.com
256
257 #############################
258 # TCP
259 PROTOCOL TCP
260 SERVER 1.2.4.8,127.0.0.1
261 PROXY 192.168.1.1:8080,192.168.1.1:8081
262
263 example.com
264
265 */
Modules_InitFromFile(StringListIterator * i)266 static int Modules_InitFromFile(StringListIterator *i)
267 {
268 #define MAX_PATH_BUFFER 384
269
270 StringChunk Args;
271 StringList Domains;
272
273 const char *FileOri;
274 char File[MAX_PATH_BUFFER];
275 FILE *fp;
276
277 ReadLineStatus Status;
278
279 const char *Protocol = NULL;
280
281 FileOri = i->Next(i);
282
283 if( FileOri == NULL )
284 {
285 return -201;
286 }
287
288 strncpy(File, FileOri, sizeof(File));
289 File[sizeof(File) - 1] = '\0';
290
291 ReplaceStr(File, "\"", "");
292
293 ExpandPath(File, sizeof(File));
294
295 fp = fopen(File, "r");
296 if( fp == NULL )
297 {
298 WARNING("Cannot open group file \"%s\".\n", File);
299 return 0;
300 }
301
302 if( StringChunk_Init(&Args, NULL) != 0 )
303 {
304 return -230;
305 }
306
307 if( StringList_Init(&Domains, NULL, NULL) != 0 )
308 {
309 return -235;
310 }
311
312 do {
313 char Buffer[384];
314 const char *Value;
315
316 Status = ReadLine(fp, Buffer, sizeof(Buffer));
317
318 if( Status == READ_TRUNCATED )
319 {
320 WARNING("Line is too long %s, file \"%s\".\n", Buffer, File);
321 Status = ReadLine_GoToNextLine(fp);
322 continue;
323 }
324
325 if( Status == READ_FAILED_OR_END )
326 {
327 break;
328 }
329
330 StrToLower(Buffer);
331
332 Value = SplitNameAndValue(Buffer, " \t=");
333 if( Value != NULL )
334 {
335 StringChunk_Add(&Args, Buffer, Value, strlen(Value) + 1);
336 } else {
337 Domains.Add(&Domains, Buffer, NULL);
338 }
339
340 } while( TRUE );
341
342 fclose(fp);
343
344 if( !StringChunk_Match_NoWildCard(&Args,
345 "protocol",
346 NULL,
347 (void **)&Protocol
348 ) ||
349 Protocol == NULL
350 )
351 {
352 ERRORMSG("No protocol specified, file \"%s\".\n", File);
353 return -270;
354 }
355
356 if( strcmp(Protocol, "udp") == 0 )
357 {
358 const char *Services = NULL;
359 const char *Parallel = "on";
360
361 StringChunk_Match_NoWildCard(&Args, "server", NULL, (void **)&Services);
362 StringChunk_Match_NoWildCard(&Args,
363 "parallel",
364 NULL,
365 (void **)&Parallel
366 );
367
368 if( Udp_Init_Core(Services, &Domains, Parallel) != 0 )
369 {
370 ERRORMSG("Loading group file \"%s\" failed.\n", File);
371 return -337;
372 }
373
374 } else if( strcmp(Protocol, "tcp") == 0 )
375 {
376 const char *Services = NULL;
377 const char *Proxies = "no";
378
379 StringChunk_Match_NoWildCard(&Args, "server", NULL, (void **)&Services);
380 StringChunk_Match_NoWildCard(&Args, "proxy", NULL, (void **)&Proxies);
381
382 if( Tcp_Init_Core(Services, &Domains, Proxies) != 0 )
383 {
384 ERRORMSG("Loading group file \"%s\" failed.\n", File);
385 return -233;
386 }
387
388 } else {
389 ERRORMSG("Unknown protocol %s, file \"%s\".\n", Protocol, File);
390 return -281;
391 }
392
393 StringChunk_Free(&Args, TRUE);
394 Domains.Free(&Domains);
395
396 return 0;
397 }
398
Modules_Init(ConfigFileInfo * ConfigInfo)399 static int Modules_Init(ConfigFileInfo *ConfigInfo)
400 {
401 StringList *ServerGroups;
402 StringListIterator i;
403
404 const char *Type;
405
406 ServerGroups = ConfigGetStringList(ConfigInfo, "ServerGroup");
407 if( ServerGroups == NULL )
408 {
409 ERRORMSG("Please set at least one server group.\n");
410 return -202;
411 }
412
413 if( StringListIterator_Init(&i, ServerGroups) != 0 )
414 {
415 return -207;
416 }
417
418 while( (Type = i.Next(&i)) != NULL )
419 {
420 if( strcmp(Type, "UDP") == 0 )
421 {
422 if( Udp_Init(&i) != 0 )
423 {
424 ERRORMSG("Initializing UDPGroups failed.\n");
425 return -218;
426 }
427 } else if( strcmp(Type, "TCP") == 0 )
428 {
429 if( Tcp_Init(&i) != 0 )
430 {
431 ERRORMSG("Initializing TCPGroups failed.\n");
432 return -226;
433 }
434 } else if( strcmp(Type, "FILE") == 0 )
435 {
436 if( Modules_InitFromFile(&i) != 0 )
437 {
438 ERRORMSG("Initializing group files failed.\n");
439 return -318;
440 }
441 } else {
442 ERRORMSG("Initializing server groups failed, near %s.\n", Type);
443 return -230;
444 }
445 }
446
447 INFO("Server groups initialized.\n", Type);
448 return 0;
449 }
450
MMgr_Init(ConfigFileInfo * ConfigInfo)451 int MMgr_Init(ConfigFileInfo *ConfigInfo)
452 {
453 if( Filter_Init(ConfigInfo) != 0 )
454 {
455 return -159;
456 }
457
458 /* Hosts & Cache */
459 if( Hosts_Init(ConfigInfo) != 0 )
460 {
461 return -165;
462 }
463
464 if( DNSCache_Init(ConfigInfo) != 0 )
465 {
466 return -164;
467 }
468
469 if( IpMiscSingleton_Init(ConfigInfo) != 0 )
470 {
471 return -176;
472 }
473
474 /* Ordinary modeles */
475 if( StringChunk_Init(&Distributor, NULL) != 0 )
476 {
477 return -10;
478 }
479
480 if( StableBuffer_Init(&Modules) != 0 )
481 {
482 return -27;
483 }
484
485 if( Array_Init(&ModuleArray,
486 sizeof(ModuleInterface *),
487 0,
488 FALSE,
489 NULL
490 )
491 != 0 )
492 {
493 return -98;
494 }
495
496 return Modules_Init(ConfigInfo);
497 }
498
MMgr_Send(IHeader * h,int BufferLength)499 int MMgr_Send(IHeader *h, int BufferLength)
500 {
501 ModuleInterface **i;
502 ModuleInterface *TheModule;
503
504 /* Determine whether to discard the query */
505 if( Filter_Out(h) )
506 {
507 return 0;
508 }
509
510 /* Hosts & Cache */
511 if( Hosts_Get(h, BufferLength) == 0 )
512 {
513 return 0;
514 }
515
516 if( DNSCache_FetchFromCache(h, BufferLength) == 0 )
517 {
518 return 0;
519 }
520
521 /* Ordinary modeles */
522 if( StringChunk_Domain_Match(&Distributor,
523 h->Domain,
524 &(h->HashValue),
525 (void **)&i
526 )
527 )
528 {
529 } else if( Array_GetUsed(&ModuleArray) > 0 ){
530 i = Array_GetBySubscript(&ModuleArray,
531 (int)(*(uint16_t *)IHEADER_TAIL(h)) %
532 Array_GetUsed(&ModuleArray)
533 );
534 } else {
535 i = NULL;
536 }
537
538 if( i == NULL || *i == NULL )
539 {
540 return -190;
541 }
542
543 TheModule = *i;
544
545 return TheModule->Send(&(TheModule->ModuleUnion), h, BufferLength);
546 }
547