2 * Copyright (c) 2010,2018 The FreeBSD Foundation
5 * This software was developed by Shteryana Sotirova Shopova under
6 * sponsorship from the FreeBSD Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 #include <sys/queue.h>
32 #include <sys/types.h>
46 #define SNMPTREE_TYPES
47 #include "target_tree.h"
48 #include "target_oid.h"
50 static struct lmodule *target_module;
51 /* For the registration. */
52 static const struct asn_oid oid_target = OIDX_snmpTargetMIB;
53 static const struct asn_oid oid_notification = OIDX_snmpNotificationMIB;
55 static uint reg_target;
56 static uint reg_notification;
58 static int32_t target_lock;
60 static const struct asn_oid oid_udp_domain = OIDX_snmpUDPDomain;
63 * Internal datastructures and forward declarations.
65 static void target_append_index(struct asn_oid *, uint,
67 static int target_decode_index(const struct asn_oid *, uint,
69 static struct target_address *target_get_address(const struct asn_oid *,
71 static struct target_address *target_get_next_address(const struct asn_oid *,
73 static struct target_param *target_get_param(const struct asn_oid *,
75 static struct target_param *target_get_next_param(const struct asn_oid *,
77 static struct target_notify *target_get_notify(const struct asn_oid *,
79 static struct target_notify *target_get_next_notify(const struct asn_oid *,
83 op_snmp_target(struct snmp_context *ctx __unused, struct snmp_value *val,
84 uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
86 struct snmpd_target_stats *ctx_stats;
88 if (val->var.subs[sub - 1] == LEAF_snmpTargetSpinLock) {
91 if (++target_lock == INT32_MAX)
93 val->v.integer = target_lock;
98 if (val->v.integer != target_lock)
99 return (SNMP_ERR_INCONS_VALUE);
101 case SNMP_OP_ROLLBACK:
106 return (SNMP_ERR_NOERROR);
107 } else if (op == SNMP_OP_SET)
108 return (SNMP_ERR_NOT_WRITEABLE);
110 if ((ctx_stats = bsnmpd_get_target_stats()) == NULL)
111 return (SNMP_ERR_GENERR);
113 if (op == SNMP_OP_GET) {
114 switch (val->var.subs[sub - 1]) {
115 case LEAF_snmpUnavailableContexts:
116 val->v.uint32 = ctx_stats->unavail_contexts;
118 case LEAF_snmpUnknownContexts:
119 val->v.uint32 = ctx_stats->unknown_contexts;
122 return (SNMP_ERR_NOSUCHNAME);
124 return (SNMP_ERR_NOERROR);
130 op_snmp_target_addrs(struct snmp_context *ctx __unused, struct snmp_value *val,
131 uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
133 char aname[SNMP_ADM_STR32_SIZ];
134 struct target_address *addrs;
138 if ((addrs = target_get_address(&val->var, sub)) == NULL)
139 return (SNMP_ERR_NOSUCHNAME);
142 case SNMP_OP_GETNEXT:
143 if ((addrs = target_get_next_address(&val->var, sub)) == NULL)
144 return (SNMP_ERR_NOSUCHNAME);
145 target_append_index(&val->var, sub, addrs->name);
149 if ((addrs = target_get_address(&val->var, sub)) == NULL &&
150 (val->var.subs[sub - 1] != LEAF_snmpTargetAddrRowStatus ||
151 val->v.integer != RowStatus_createAndWait))
152 return (SNMP_ERR_NOSUCHNAME);
155 if (community != COMM_INITIALIZE &&
156 addrs->type == StorageType_readOnly)
157 return (SNMP_ERR_NOT_WRITEABLE);
158 if (addrs->status == RowStatus_active &&
159 val->v.integer != RowStatus_destroy)
160 return (SNMP_ERR_INCONS_VALUE);
163 switch (val->var.subs[sub - 1]) {
164 case LEAF_snmpTargetAddrTDomain:
165 return (SNMP_ERR_INCONS_VALUE);
166 case LEAF_snmpTargetAddrTAddress:
167 if (val->v.octetstring.len != SNMP_UDP_ADDR_SIZ)
168 return (SNMP_ERR_INCONS_VALUE);
169 ctx->scratch->ptr1 = malloc(SNMP_UDP_ADDR_SIZ);
170 if (ctx->scratch->ptr1 == NULL)
171 return (SNMP_ERR_GENERR);
172 memcpy(ctx->scratch->ptr1, addrs->address,
174 memcpy(addrs->address, val->v.octetstring.octets,
178 case LEAF_snmpTargetAddrTagList:
179 if (val->v.octetstring.len >= SNMP_TAG_SIZ)
180 return (SNMP_ERR_INCONS_VALUE);
181 ctx->scratch->int1 = strlen(addrs->taglist) + 1;
182 ctx->scratch->ptr1 = malloc(ctx->scratch->int1);
183 if (ctx->scratch->ptr1 == NULL)
184 return (SNMP_ERR_GENERR);
185 strlcpy(ctx->scratch->ptr1, addrs->taglist,
187 memcpy(addrs->taglist, val->v.octetstring.octets,
188 val->v.octetstring.len);
189 addrs->taglist[val->v.octetstring.len] = '\0';
192 case LEAF_snmpTargetAddrParams:
193 if (val->v.octetstring.len >= SNMP_ADM_STR32_SIZ)
194 return (SNMP_ERR_INCONS_VALUE);
195 ctx->scratch->int1 = strlen(addrs->paramname) + 1;
196 ctx->scratch->ptr1 = malloc(ctx->scratch->int1);
197 if (ctx->scratch->ptr1 == NULL)
198 return (SNMP_ERR_GENERR);
199 strlcpy(ctx->scratch->ptr1, addrs->paramname,
201 memcpy(addrs->paramname, val->v.octetstring.octets,
202 val->v.octetstring.len);
203 addrs->paramname[val->v.octetstring.len] = '\0';
206 case LEAF_snmpTargetAddrRetryCount:
207 ctx->scratch->int1 = addrs->retry;
208 addrs->retry = val->v.integer;
211 case LEAF_snmpTargetAddrTimeout:
212 ctx->scratch->int1 = addrs->timeout;
213 addrs->timeout = val->v.integer / 10;
216 case LEAF_snmpTargetAddrStorageType:
217 return (SNMP_ERR_INCONS_VALUE);
219 case LEAF_snmpTargetAddrRowStatus:
221 if (val->v.integer != RowStatus_active &&
222 val->v.integer != RowStatus_destroy)
223 return (SNMP_ERR_INCONS_VALUE);
224 if (val->v.integer == RowStatus_active &&
225 (addrs->address[0] == 0 ||
226 strlen(addrs->taglist) == 0 ||
227 strlen(addrs->paramname) == 0))
228 return (SNMP_ERR_INCONS_VALUE);
229 ctx->scratch->int1 = addrs->status;
230 addrs->status = val->v.integer;
231 return (SNMP_ERR_NOERROR);
233 if (val->v.integer != RowStatus_createAndWait ||
234 target_decode_index(&val->var, sub, aname) < 0)
235 return (SNMP_ERR_INCONS_VALUE);
236 if ((addrs = target_new_address(aname)) == NULL)
237 return (SNMP_ERR_GENERR);
238 addrs->status = RowStatus_destroy;
239 if (community != COMM_INITIALIZE)
240 addrs->type = StorageType_volatile;
242 addrs->type = StorageType_readOnly;
245 return (SNMP_ERR_NOERROR);
248 switch (val->var.subs[sub - 1]) {
249 case LEAF_snmpTargetAddrTAddress:
250 case LEAF_snmpTargetAddrTagList:
251 case LEAF_snmpTargetAddrParams:
252 free(ctx->scratch->ptr1);
254 case LEAF_snmpTargetAddrRowStatus:
255 if ((addrs = target_get_address(&val->var, sub)) == NULL)
256 return (SNMP_ERR_GENERR);
257 if (val->v.integer == RowStatus_destroy)
258 return (target_delete_address(addrs));
259 else if (val->v.integer == RowStatus_active)
260 return (target_activate_address(addrs));
265 return (SNMP_ERR_NOERROR);
267 case SNMP_OP_ROLLBACK:
268 if ((addrs = target_get_address(&val->var, sub)) == NULL)
269 return (SNMP_ERR_GENERR);
271 switch (val->var.subs[sub - 1]) {
272 case LEAF_snmpTargetAddrTAddress:
273 memcpy(addrs->address, ctx->scratch->ptr1,
275 free(ctx->scratch->ptr1);
278 case LEAF_snmpTargetAddrTagList:
279 strlcpy(addrs->taglist, ctx->scratch->ptr1,
281 free(ctx->scratch->ptr1);
284 case LEAF_snmpTargetAddrParams:
285 strlcpy(addrs->paramname, ctx->scratch->ptr1,
287 free(ctx->scratch->ptr1);
290 case LEAF_snmpTargetAddrRetryCount:
291 addrs->retry = ctx->scratch->int1;
294 case LEAF_snmpTargetAddrTimeout:
295 addrs->timeout = ctx->scratch->int1;
298 case LEAF_snmpTargetAddrRowStatus:
299 if (ctx->scratch->int1 == RowStatus_destroy)
300 return (target_delete_address(addrs));
305 return (SNMP_ERR_NOERROR);
311 switch (val->var.subs[sub - 1]) {
312 case LEAF_snmpTargetAddrTDomain:
313 return (oid_get(val, &oid_udp_domain));
314 case LEAF_snmpTargetAddrTAddress:
315 return (string_get(val, addrs->address, SNMP_UDP_ADDR_SIZ));
316 case LEAF_snmpTargetAddrTimeout:
317 val->v.integer = addrs->timeout;
319 case LEAF_snmpTargetAddrRetryCount:
320 val->v.integer = addrs->retry;
322 case LEAF_snmpTargetAddrTagList:
323 return (string_get(val, addrs->taglist, -1));
324 case LEAF_snmpTargetAddrParams:
325 return (string_get(val, addrs->paramname, -1));
326 case LEAF_snmpTargetAddrStorageType:
327 val->v.integer = addrs->type;
329 case LEAF_snmpTargetAddrRowStatus:
330 val->v.integer = addrs->status;
336 return (SNMP_ERR_NOERROR);
340 op_snmp_target_params(struct snmp_context *ctx __unused, struct snmp_value *val,
341 uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
343 char pname[SNMP_ADM_STR32_SIZ];
344 struct target_param *param;
348 if ((param = target_get_param(&val->var, sub)) == NULL)
349 return (SNMP_ERR_NOSUCHNAME);
352 case SNMP_OP_GETNEXT:
353 if ((param = target_get_next_param(&val->var, sub)) == NULL)
354 return (SNMP_ERR_NOSUCHNAME);
355 target_append_index(&val->var, sub, param->name);
359 if ((param = target_get_param(&val->var, sub)) == NULL &&
360 (val->var.subs[sub - 1] != LEAF_snmpTargetParamsRowStatus ||
361 val->v.integer != RowStatus_createAndWait))
362 return (SNMP_ERR_NOSUCHNAME);
365 if (community != COMM_INITIALIZE &&
366 param->type == StorageType_readOnly)
367 return (SNMP_ERR_NOT_WRITEABLE);
368 if (param->status == RowStatus_active &&
369 val->v.integer != RowStatus_destroy)
370 return (SNMP_ERR_INCONS_VALUE);
373 switch (val->var.subs[sub - 1]) {
374 case LEAF_snmpTargetParamsMPModel:
375 if (val->v.integer != SNMP_MPM_SNMP_V1 &&
376 val->v.integer != SNMP_MPM_SNMP_V2c &&
377 val->v.integer != SNMP_MPM_SNMP_V3)
378 return (SNMP_ERR_INCONS_VALUE);
379 ctx->scratch->int1 = param->mpmodel;
380 param->mpmodel = val->v.integer;
383 case LEAF_snmpTargetParamsSecurityModel:
384 if (val->v.integer != SNMP_SECMODEL_SNMPv1 &&
385 val->v.integer != SNMP_SECMODEL_SNMPv2c &&
386 val->v.integer != SNMP_SECMODEL_USM)
387 return (SNMP_ERR_INCONS_VALUE);
388 ctx->scratch->int1 = param->sec_model;
389 param->sec_model = val->v.integer;
392 case LEAF_snmpTargetParamsSecurityName:
393 if (val->v.octetstring.len >= SNMP_ADM_STR32_SIZ)
394 return (SNMP_ERR_INCONS_VALUE);
395 ctx->scratch->int1 = strlen(param->secname) + 1;
396 ctx->scratch->ptr1 = malloc(ctx->scratch->int1);
397 if (ctx->scratch->ptr1 == NULL)
398 return (SNMP_ERR_GENERR);
399 strlcpy(ctx->scratch->ptr1, param->secname,
401 memcpy(param->secname, val->v.octetstring.octets,
402 val->v.octetstring.len);
403 param->secname[val->v.octetstring.len] = '\0';
406 case LEAF_snmpTargetParamsSecurityLevel:
407 if (val->v.integer != SNMP_noAuthNoPriv &&
408 val->v.integer != SNMP_authNoPriv &&
409 val->v.integer != SNMP_authPriv)
410 return (SNMP_ERR_INCONS_VALUE);
411 ctx->scratch->int1 = param->sec_level;
412 param->sec_level = val->v.integer;
415 case LEAF_snmpTargetParamsStorageType:
416 return (SNMP_ERR_INCONS_VALUE);
418 case LEAF_snmpTargetParamsRowStatus:
420 if (val->v.integer != RowStatus_active &&
421 val->v.integer != RowStatus_destroy)
422 return (SNMP_ERR_INCONS_VALUE);
423 if (val->v.integer == RowStatus_active &&
424 (param->sec_model == 0 ||
425 param->sec_level == 0 ||
426 strlen(param->secname) == 0))
427 return (SNMP_ERR_INCONS_VALUE);
428 ctx->scratch->int1 = param->status;
429 param->status = val->v.integer;
430 return (SNMP_ERR_NOERROR);
432 if (val->v.integer != RowStatus_createAndWait ||
433 target_decode_index(&val->var, sub, pname) < 0)
434 return (SNMP_ERR_INCONS_VALUE);
435 if ((param = target_new_param(pname)) == NULL)
436 return (SNMP_ERR_GENERR);
437 param->status = RowStatus_destroy;
438 if (community != COMM_INITIALIZE)
439 param->type = StorageType_volatile;
441 param->type = StorageType_readOnly;
444 return (SNMP_ERR_NOERROR);
447 switch (val->var.subs[sub - 1]) {
448 case LEAF_snmpTargetParamsSecurityName:
449 free(ctx->scratch->ptr1);
451 case LEAF_snmpTargetParamsRowStatus:
452 if ((param = target_get_param(&val->var, sub)) == NULL)
453 return (SNMP_ERR_GENERR);
454 if (val->v.integer == RowStatus_destroy)
455 return (target_delete_param(param));
460 return (SNMP_ERR_NOERROR);
462 case SNMP_OP_ROLLBACK:
463 if ((param = target_get_param(&val->var, sub)) == NULL &&
464 (val->var.subs[sub - 1] != LEAF_snmpTargetParamsRowStatus ||
465 val->v.integer != RowStatus_createAndWait))
466 return (SNMP_ERR_GENERR);
467 switch (val->var.subs[sub - 1]) {
468 case LEAF_snmpTargetParamsMPModel:
469 param->mpmodel = ctx->scratch->int1;
471 case LEAF_snmpTargetParamsSecurityModel:
472 param->sec_model = ctx->scratch->int1;
474 case LEAF_snmpTargetParamsSecurityName:
475 strlcpy(param->secname, ctx->scratch->ptr1,
476 sizeof(param->secname));
477 free(ctx->scratch->ptr1);
479 case LEAF_snmpTargetParamsSecurityLevel:
480 param->sec_level = ctx->scratch->int1;
482 case LEAF_snmpTargetParamsRowStatus:
483 if (ctx->scratch->int1 == RowStatus_destroy)
484 return (target_delete_param(param));
490 return (SNMP_ERR_NOERROR);
496 switch (val->var.subs[sub - 1]) {
497 case LEAF_snmpTargetParamsMPModel:
498 val->v.integer = param->mpmodel;
500 case LEAF_snmpTargetParamsSecurityModel:
501 val->v.integer = param->sec_model;
503 case LEAF_snmpTargetParamsSecurityName:
504 return (string_get(val, param->secname, -1));
505 case LEAF_snmpTargetParamsSecurityLevel:
506 val->v.integer = param->sec_level;
508 case LEAF_snmpTargetParamsStorageType:
509 val->v.integer = param->type;
511 case LEAF_snmpTargetParamsRowStatus:
512 val->v.integer = param->status;
518 return (SNMP_ERR_NOERROR);
522 op_snmp_notify(struct snmp_context *ctx __unused, struct snmp_value *val,
523 uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
525 char nname[SNMP_ADM_STR32_SIZ];
526 struct target_notify *notify;
530 if ((notify = target_get_notify(&val->var, sub)) == NULL)
531 return (SNMP_ERR_NOSUCHNAME);
534 case SNMP_OP_GETNEXT:
535 if ((notify = target_get_next_notify(&val->var, sub)) == NULL)
536 return (SNMP_ERR_NOSUCHNAME);
537 target_append_index(&val->var, sub, notify->name);
541 if ((notify = target_get_notify(&val->var, sub)) == NULL &&
542 (val->var.subs[sub - 1] != LEAF_snmpNotifyRowStatus ||
543 val->v.integer != RowStatus_createAndGo))
544 return (SNMP_ERR_NOSUCHNAME);
546 if (notify != NULL) {
547 if (community != COMM_INITIALIZE &&
548 notify->type == StorageType_readOnly)
549 return (SNMP_ERR_NOT_WRITEABLE);
552 switch (val->var.subs[sub - 1]) {
553 case LEAF_snmpNotifyTag:
554 if (val->v.octetstring.len >= SNMP_TAG_SIZ)
555 return (SNMP_ERR_INCONS_VALUE);
556 ctx->scratch->int1 = strlen(notify->taglist) + 1;
557 ctx->scratch->ptr1 = malloc(ctx->scratch->int1);
558 if (ctx->scratch->ptr1 == NULL)
559 return (SNMP_ERR_GENERR);
560 strlcpy(ctx->scratch->ptr1, notify->taglist,
562 memcpy(notify->taglist, val->v.octetstring.octets,
563 val->v.octetstring.len);
564 notify->taglist[val->v.octetstring.len] = '\0';
567 case LEAF_snmpNotifyType:
569 case LEAF_snmpNotifyStorageType:
570 return (SNMP_ERR_INCONS_VALUE);
571 case LEAF_snmpNotifyRowStatus:
572 if (notify != NULL) {
573 if (val->v.integer != RowStatus_active &&
574 val->v.integer != RowStatus_destroy)
575 return (SNMP_ERR_INCONS_VALUE);
576 ctx->scratch->int1 = notify->status;
577 notify->status = val->v.integer;
578 return (SNMP_ERR_NOERROR);
580 if (val->v.integer != RowStatus_createAndGo ||
581 target_decode_index(&val->var, sub, nname) < 0)
582 return (SNMP_ERR_INCONS_VALUE);
583 if ((notify = target_new_notify(nname)) == NULL)
584 return (SNMP_ERR_GENERR);
585 notify->status = RowStatus_destroy;
586 if (community != COMM_INITIALIZE)
587 notify->type = StorageType_volatile;
589 notify->type = StorageType_readOnly;
592 return (SNMP_ERR_NOERROR);
595 switch (val->var.subs[sub - 1]) {
596 case LEAF_snmpNotifyTag:
597 free(ctx->scratch->ptr1);
599 case LEAF_snmpNotifyRowStatus:
600 notify = target_get_notify(&val->var, sub);
602 return (SNMP_ERR_GENERR);
603 if (val->v.integer == RowStatus_destroy)
604 return (target_delete_notify(notify));
606 notify->status = RowStatus_active;
611 return (SNMP_ERR_NOERROR);
613 case SNMP_OP_ROLLBACK:
614 if ((notify = target_get_notify(&val->var, sub)) == NULL)
615 return (SNMP_ERR_GENERR);
617 switch (val->var.subs[sub - 1]) {
618 case LEAF_snmpNotifyTag:
619 strlcpy(notify->taglist, ctx->scratch->ptr1,
621 free(ctx->scratch->ptr1);
623 case LEAF_snmpNotifyRowStatus:
624 if (ctx->scratch->int1 == RowStatus_destroy)
625 return (target_delete_notify(notify));
630 return (SNMP_ERR_NOERROR);
637 switch (val->var.subs[sub - 1]) {
638 case LEAF_snmpNotifyTag:
639 return (string_get(val, notify->taglist, -1));
640 case LEAF_snmpNotifyType:
641 val->v.integer = snmpNotifyType_trap;
643 case LEAF_snmpNotifyStorageType:
644 val->v.integer = notify->type;
646 case LEAF_snmpNotifyRowStatus:
647 val->v.integer = notify->status;
653 return (SNMP_ERR_NOERROR);
657 target_append_index(struct asn_oid *oid, uint sub, const char *name)
661 oid->len = sub + strlen(name);
662 for (i = 0; i < strlen(name); i++)
663 oid->subs[sub + i] = name[i];
667 target_decode_index(const struct asn_oid *oid, uint sub, char *name)
671 if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >=
675 for (i = 0; i < oid->subs[sub]; i++)
676 name[i] = oid->subs[sub + i + 1];
682 static struct target_address *
683 target_get_address(const struct asn_oid *oid, uint sub)
685 char aname[SNMP_ADM_STR32_SIZ];
686 struct target_address *addrs;
688 if (target_decode_index(oid, sub, aname) < 0)
691 for (addrs = target_first_address(); addrs != NULL;
692 addrs = target_next_address(addrs))
693 if (strcmp(aname, addrs->name) == 0)
699 static struct target_address *
700 target_get_next_address(const struct asn_oid * oid, uint sub)
702 char aname[SNMP_ADM_STR32_SIZ];
703 struct target_address *addrs;
705 if (oid->len - sub == 0)
706 return (target_first_address());
708 if (target_decode_index(oid, sub, aname) < 0)
711 for (addrs = target_first_address(); addrs != NULL;
712 addrs = target_next_address(addrs))
713 if (strcmp(aname, addrs->name) == 0)
714 return (target_next_address(addrs));
719 static struct target_param *
720 target_get_param(const struct asn_oid *oid, uint sub)
722 char pname[SNMP_ADM_STR32_SIZ];
723 struct target_param *param;
725 if (target_decode_index(oid, sub, pname) < 0)
728 for (param = target_first_param(); param != NULL;
729 param = target_next_param(param))
730 if (strcmp(pname, param->name) == 0)
736 static struct target_param *
737 target_get_next_param(const struct asn_oid *oid, uint sub)
739 char pname[SNMP_ADM_STR32_SIZ];
740 struct target_param *param;
742 if (oid->len - sub == 0)
743 return (target_first_param());
745 if (target_decode_index(oid, sub, pname) < 0)
748 for (param = target_first_param(); param != NULL;
749 param = target_next_param(param))
750 if (strcmp(pname, param->name) == 0)
751 return (target_next_param(param));
756 static struct target_notify *
757 target_get_notify(const struct asn_oid *oid, uint sub)
759 char nname[SNMP_ADM_STR32_SIZ];
760 struct target_notify *notify;
762 if (target_decode_index(oid, sub, nname) < 0)
765 for (notify = target_first_notify(); notify != NULL;
766 notify = target_next_notify(notify))
767 if (strcmp(nname, notify->name) == 0)
773 static struct target_notify *
774 target_get_next_notify(const struct asn_oid *oid, uint sub)
776 char nname[SNMP_ADM_STR32_SIZ];
777 struct target_notify *notify;
779 if (oid->len - sub == 0)
780 return (target_first_notify());
782 if (target_decode_index(oid, sub, nname) < 0)
785 for (notify = target_first_notify(); notify != NULL;
786 notify = target_next_notify(notify))
787 if (strcmp(nname, notify->name) == 0)
788 return (target_next_notify(notify));
794 target_init(struct lmodule *mod, int argc __unused, char *argv[] __unused)
797 target_lock = random();
807 or_unregister(reg_target);
808 or_unregister(reg_notification);
816 reg_target = or_register(&oid_target,
817 "The MIB module for managing SNMP Management Targets.",
819 reg_notification = or_register(&oid_notification,
820 "The MIB module for configuring generation of SNMP notifications.",
827 /* XXX: dump the module stats & list of mgmt targets */
830 static const char target_comment[] = \
831 "This module implements SNMP Management Target MIB Module defined in RFC 3413.";
833 extern const struct snmp_module config;
834 const struct snmp_module config = {
835 .comment = target_comment,
838 .start = target_start,
839 .tree = target_ctree,
841 .tree_size = target_CTREE_SIZE,