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