1 #include <net-snmp/net-snmp-config.h>
2
3 #include <stdlib.h>
4 #include <string.h>
5
6 #include <net-snmp/net-snmp-includes.h>
7 #include <net-snmp/library/snmp_transport.h>
8
9 static char**
create_word_array_helper(const char * cptr,size_t idx,char * tmp,size_t tmplen)10 create_word_array_helper(const char* cptr, size_t idx, char* tmp, size_t tmplen)
11 {
12 char* item;
13 char** res;
14 cptr = copy_nword_const(cptr, tmp, tmplen);
15 item = strdup(tmp);
16 if (cptr)
17 res = create_word_array_helper(cptr, idx + 1, tmp, tmplen);
18 else {
19 res = (char**)malloc(sizeof(char*) * (idx + 2));
20 res[idx + 1] = NULL;
21 }
22 res[idx] = item;
23 return res;
24 }
25
26 static char**
create_word_array(const char * cptr)27 create_word_array(const char* cptr)
28 {
29 size_t tmplen = strlen(cptr);
30 char* tmp = (char*)malloc(tmplen + 1);
31 char** res = create_word_array_helper(cptr, 0, tmp, tmplen + 1);
32 free(tmp);
33 return res;
34 }
35
36 static void
destroy_word_array(char ** arr)37 destroy_word_array(char** arr)
38 {
39 if (arr) {
40 char** run = arr;
41 while(*run) {
42 free(*run);
43 ++run;
44 }
45 free(arr);
46 }
47 }
48
49 struct netsnmp_lookup_domain {
50 char* application;
51 char** userDomain;
52 char** domain;
53 struct netsnmp_lookup_domain* next;
54 };
55
56 static struct netsnmp_lookup_domain* domains = NULL;
57
58 int
netsnmp_register_default_domain(const char * application,const char * domain)59 netsnmp_register_default_domain(const char* application, const char* domain)
60 {
61 struct netsnmp_lookup_domain *run = domains, *prev = NULL;
62 int res = 0;
63
64 while (run != NULL && strcmp(run->application, application) < 0) {
65 prev = run;
66 run = run->next;
67 }
68 if (run && strcmp(run->application, application) == 0) {
69 if (run->domain != NULL) {
70 destroy_word_array(run->domain);
71 run->domain = NULL;
72 res = 1;
73 }
74 } else {
75 run = SNMP_MALLOC_STRUCT(netsnmp_lookup_domain);
76 run->application = strdup(application);
77 run->userDomain = NULL;
78 if (prev) {
79 run->next = prev->next;
80 prev->next = run;
81 } else {
82 run->next = domains;
83 domains = run;
84 }
85 }
86 if (domain) {
87 run->domain = create_word_array(domain);
88 } else if (run->userDomain == NULL) {
89 if (prev)
90 prev->next = run->next;
91 else
92 domains = run->next;
93 free(run->application);
94 free(run);
95 }
96 return res;
97 }
98
99 void
netsnmp_clear_default_domain(void)100 netsnmp_clear_default_domain(void)
101 {
102 while (domains) {
103 struct netsnmp_lookup_domain *tmp = domains;
104 domains = domains->next;
105 free(tmp->application);
106 destroy_word_array(tmp->userDomain);
107 destroy_word_array(tmp->domain);
108 free(tmp);
109 }
110 }
111
112 static void
netsnmp_register_user_domain(const char * token,char * cptr)113 netsnmp_register_user_domain(const char* token, char* cptr)
114 {
115 struct netsnmp_lookup_domain *run = domains, *prev = NULL;
116 size_t len = strlen(cptr) + 1;
117 char* application = (char*)malloc(len);
118 char** domain;
119
120 {
121 char* cp = copy_nword(cptr, application, len);
122 if (cp == NULL) {
123 netsnmp_config_error("No domain(s) in registration of "
124 "defDomain \"%s\"", application);
125 free(application);
126 return;
127 }
128 domain = create_word_array(cp);
129 }
130
131 while (run != NULL && strcmp(run->application, application) < 0) {
132 prev = run;
133 run = run->next;
134 }
135 if (run && strcmp(run->application, application) == 0) {
136 if (run->userDomain != NULL) {
137 config_perror("Default transport already registered for this "
138 "application");
139 destroy_word_array(domain);
140 free(application);
141 return;
142 }
143 } else {
144 run = SNMP_MALLOC_STRUCT(netsnmp_lookup_domain);
145 run->application = strdup(application);
146 run->domain = NULL;
147 if (prev) {
148 run->next = prev->next;
149 prev->next = run;
150 } else {
151 run->next = domains;
152 domains = run;
153 }
154 }
155 run->userDomain = domain;
156 free(application);
157 }
158
159 static void
netsnmp_clear_user_domain(void)160 netsnmp_clear_user_domain(void)
161 {
162 struct netsnmp_lookup_domain *run = domains, *prev = NULL;
163
164 while (run) {
165 if (run->userDomain != NULL) {
166 destroy_word_array(run->userDomain);
167 run->userDomain = NULL;
168 }
169 if (run->domain == NULL) {
170 struct netsnmp_lookup_domain *tmp = run;
171 if (prev)
172 run = prev->next = run->next;
173 else
174 run = domains = run->next;
175 free(tmp->application);
176 free(tmp);
177 } else {
178 prev = run;
179 run = run->next;
180 }
181 }
182 }
183
184 const char* const *
netsnmp_lookup_default_domains(const char * application)185 netsnmp_lookup_default_domains(const char* application)
186 {
187 const char * const * res;
188
189 if (application == NULL)
190 res = NULL;
191 else {
192 struct netsnmp_lookup_domain *run = domains;
193
194 while (run && strcmp(run->application, application) < 0)
195 run = run->next;
196 if (run && strcmp(run->application, application) == 0)
197 if (run->userDomain)
198 res = (const char * const *)run->userDomain;
199 else
200 res = (const char * const *)run->domain;
201 else
202 res = NULL;
203 }
204 DEBUGMSGTL(("defaults",
205 "netsnmp_lookup_default_domain(\"%s\") ->",
206 application ? application : "[NIL]"));
207 if (res) {
208 const char * const * r = res;
209 while(*r) {
210 DEBUGMSG(("defaults", " \"%s\"", *r));
211 ++r;
212 }
213 DEBUGMSG(("defaults", "\n"));
214 } else
215 DEBUGMSG(("defaults", " \"[NIL]\"\n"));
216 return res;
217 }
218
219 const char*
netsnmp_lookup_default_domain(const char * application)220 netsnmp_lookup_default_domain(const char* application)
221 {
222 const char * const * res = netsnmp_lookup_default_domains(application);
223 return (res ? *res : NULL);
224 }
225
226 struct netsnmp_lookup_target {
227 char* application;
228 char* domain;
229 char* userTarget;
230 char* target;
231 struct netsnmp_lookup_target* next;
232 };
233
234 static struct netsnmp_lookup_target* targets = NULL;
235
236 /**
237 * Add an (application, domain, target) triplet to the targets list if target
238 * != NULL. Remove an entry if target == NULL and the userTarget pointer for
239 * the entry found is also NULL. Keep at most one target per (application,
240 * domain) pair.
241 *
242 * @return 1 if an entry for (application, domain) was already present in the
243 * targets list or 0 if such an entry was not yet present in the targets list.
244 */
245 int
netsnmp_register_default_target(const char * application,const char * domain,const char * target)246 netsnmp_register_default_target(const char* application, const char* domain,
247 const char* target)
248 {
249 struct netsnmp_lookup_target *run = targets, *prev = NULL;
250 int i = 0, res = 0;
251 while (run && ((i = strcmp(run->application, application)) < 0 ||
252 (i == 0 && strcmp(run->domain, domain) < 0))) {
253 prev = run;
254 run = run->next;
255 }
256 if (run && i == 0 && strcmp(run->domain, domain) == 0) {
257 if (run->target != NULL) {
258 free(run->target);
259 run->target = NULL;
260 res = 1;
261 }
262 } else {
263 run = SNMP_MALLOC_STRUCT(netsnmp_lookup_target);
264 run->application = strdup(application);
265 run->domain = strdup(domain);
266 run->userTarget = NULL;
267 if (prev) {
268 run->next = prev->next;
269 prev->next = run;
270 } else {
271 run->next = targets;
272 targets = run;
273 }
274 }
275 if (target) {
276 run->target = strdup(target);
277 } else if (run->userTarget == NULL) {
278 if (prev)
279 prev->next = run->next;
280 else
281 targets = run->next;
282 free(run->domain);
283 free(run->application);
284 free(run);
285 }
286 return res;
287 }
288
289 /**
290 * Clear the targets list.
291 */
292 void
netsnmp_clear_default_target(void)293 netsnmp_clear_default_target(void)
294 {
295 while (targets) {
296 struct netsnmp_lookup_target *tmp = targets;
297 targets = targets->next;
298 free(tmp->application);
299 free(tmp->domain);
300 free(tmp->userTarget);
301 free(tmp->target);
302 free(tmp);
303 }
304 }
305
306 static void
netsnmp_register_user_target(const char * token,char * cptr)307 netsnmp_register_user_target(const char* token, char* cptr)
308 {
309 struct netsnmp_lookup_target *run = targets, *prev = NULL;
310 size_t len = strlen(cptr) + 1;
311 char* application = (char*)malloc(len);
312 char* domain = (char*)malloc(len);
313 char* target = (char*)malloc(len);
314 int i = 0;
315
316 {
317 char* cp = copy_nword(cptr, application, len);
318 if (cp == NULL) {
319 netsnmp_config_error("No domain and target in registration of "
320 "defTarget \"%s\"", application);
321 goto done;
322 }
323 cp = copy_nword(cp, domain, len);
324 if (cp == NULL) {
325 netsnmp_config_error("No target in registration of "
326 "defTarget \"%s\" \"%s\"",
327 application, domain);
328 goto done;
329 }
330 cp = copy_nword(cp, target, len);
331 if (cp)
332 config_pwarn("Trailing junk found");
333 }
334
335 while (run && ((i = strcmp(run->application, application)) < 0 ||
336 (i == 0 && strcmp(run->domain, domain) < 0))) {
337 prev = run;
338 run = run->next;
339 }
340 if (run && i == 0 && strcmp(run->domain, domain) == 0) {
341 if (run->userTarget != NULL) {
342 config_perror("Default target already registered for this "
343 "application-domain combination");
344 goto done;
345 }
346 } else {
347 run = SNMP_MALLOC_STRUCT(netsnmp_lookup_target);
348 run->application = strdup(application);
349 run->domain = strdup(domain);
350 run->target = NULL;
351 if (prev) {
352 run->next = prev->next;
353 prev->next = run;
354 } else {
355 run->next = targets;
356 targets = run;
357 }
358 }
359 run->userTarget = strdup(target);
360 done:
361 free(target);
362 free(domain);
363 free(application);
364 }
365
366 static void
netsnmp_clear_user_target(void)367 netsnmp_clear_user_target(void)
368 {
369 struct netsnmp_lookup_target *run = targets, *prev = NULL;
370
371 while (run) {
372 if (run->userTarget != NULL) {
373 free(run->userTarget);
374 run->userTarget = NULL;
375 }
376 if (run->target == NULL) {
377 struct netsnmp_lookup_target *tmp = run;
378 if (prev)
379 run = prev->next = run->next;
380 else
381 run = targets = run->next;
382 free(tmp->application);
383 free(tmp->domain);
384 free(tmp);
385 } else {
386 prev = run;
387 run = run->next;
388 }
389 }
390 }
391
392 const char*
netsnmp_lookup_default_target(const char * application,const char * domain)393 netsnmp_lookup_default_target(const char* application, const char* domain)
394 {
395 int i = 0;
396 struct netsnmp_lookup_target *run = targets;
397 const char *res;
398
399 if (application == NULL || domain == NULL)
400 res = NULL;
401 else {
402 while (run && ((i = strcmp(run->application, application)) < 0 ||
403 (i == 0 && strcmp(run->domain, domain) < 0)))
404 run = run->next;
405 if (run && i == 0 && strcmp(run->domain, domain) == 0)
406 if (run->userTarget != NULL)
407 res = run->userTarget;
408 else
409 res = run->target;
410 else
411 res = NULL;
412 }
413 DEBUGMSGTL(("defaults",
414 "netsnmp_lookup_default_target(\"%s\", \"%s\") -> \"%s\"\n",
415 application ? application : "[NIL]",
416 domain ? domain : "[NIL]",
417 res ? res : "[NIL]"));
418 return res;
419 }
420
421 void
netsnmp_register_service_handlers(void)422 netsnmp_register_service_handlers(void)
423 {
424 register_config_handler("snmp:", "defDomain",
425 netsnmp_register_user_domain,
426 netsnmp_clear_user_domain,
427 "application domain");
428 register_config_handler("snmp:", "defTarget",
429 netsnmp_register_user_target,
430 netsnmp_clear_user_target,
431 "application domain target");
432 }
433