2 * Copyright (c) 2010 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 #include "target_tree.h"
47 #include "target_oid.h"
49 static struct lmodule *target_module;
50 /* For the registration. */
51 static const struct asn_oid oid_target = OIDX_snmpTargetMIB;
52 static const struct asn_oid oid_notification = OIDX_snmpNotificationMIB;
54 static uint reg_target;
55 static uint reg_notification;
57 static int32_t target_lock;
59 static const struct asn_oid oid_udp_domain = OIDX_snmpUDPDomain;
62 * Internal datastructures and forward declarations.
64 static void target_append_index(struct asn_oid *, uint,
66 static int target_decode_index(const struct asn_oid *, uint,
68 static struct target_address *target_get_address(const struct asn_oid *,
70 static struct target_address *target_get_next_address(const struct asn_oid *,
72 static struct target_param *target_get_param(const struct asn_oid *,
74 static struct target_param *target_get_next_param(const struct asn_oid *,
76 static struct target_notify *target_get_notify(const struct asn_oid *,
78 static struct target_notify *target_get_next_notify(const struct asn_oid *,
82 op_snmp_target(struct snmp_context *ctx __unused, struct snmp_value *val,
83 uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
85 struct snmpd_target_stats *ctx_stats;
87 if (val->var.subs[sub - 1] == LEAF_snmpTargetSpinLock) {
90 if (++target_lock == INT32_MAX)
92 val->v.integer = target_lock;
97 if (val->v.integer != target_lock)
98 return (SNMP_ERR_INCONS_VALUE);
100 case SNMP_OP_ROLLBACK:
105 return (SNMP_ERR_NOERROR);
106 } else if (op == SNMP_OP_SET)
107 return (SNMP_ERR_NOT_WRITEABLE);
109 if ((ctx_stats = bsnmpd_get_target_stats()) == NULL)
110 return (SNMP_ERR_GENERR);
112 if (op == SNMP_OP_GET) {
113 switch (val->var.subs[sub - 1]) {
114 case LEAF_snmpUnavailableContexts:
115 val->v.uint32 = ctx_stats->unavail_contexts;
117 case LEAF_snmpUnknownContexts:
118 val->v.uint32 = ctx_stats->unknown_contexts;
121 return (SNMP_ERR_NOSUCHNAME);
123 return (SNMP_ERR_NOERROR);
129 op_snmp_target_addrs(struct snmp_context *ctx __unused, struct snmp_value *val,
130 uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
132 char aname[SNMP_ADM_STR32_SIZ];
133 struct target_address *addrs;
137 if ((addrs = target_get_address(&val->var, sub)) == NULL)
138 return (SNMP_ERR_NOSUCHNAME);
141 case SNMP_OP_GETNEXT:
142 if ((addrs = target_get_next_address(&val->var, sub)) == NULL)
143 return (SNMP_ERR_NOSUCHNAME);
144 target_append_index(&val->var, sub, addrs->name);
148 if ((addrs = target_get_address(&val->var, sub)) == NULL &&
149 (val->var.subs[sub - 1] != LEAF_snmpTargetAddrRowStatus ||
150 val->v.integer != RowStatus_createAndWait))
151 return (SNMP_ERR_NOSUCHNAME);
154 if (community != COMM_INITIALIZE &&
155 addrs->type == StorageType_readOnly)
156 return (SNMP_ERR_NOT_WRITEABLE);
157 if (addrs->status == RowStatus_active &&
158 val->v.integer != RowStatus_destroy)
159 return (SNMP_ERR_INCONS_VALUE);
162 switch (val->var.subs[sub - 1]) {
163 case LEAF_snmpTargetAddrTDomain:
164 return (SNMP_ERR_INCONS_VALUE);
165 case LEAF_snmpTargetAddrTAddress:
166 if (val->v.octetstring.len != SNMP_UDP_ADDR_SIZ)
167 return (SNMP_ERR_INCONS_VALUE);
168 ctx->scratch->ptr1 = malloc(SNMP_UDP_ADDR_SIZ);
169 if (ctx->scratch->ptr1 == NULL)
170 return (SNMP_ERR_GENERR);
171 memcpy(ctx->scratch->ptr1, addrs->address,
173 memcpy(addrs->address, val->v.octetstring.octets,
177 case LEAF_snmpTargetAddrTagList:
178 if (val->v.octetstring.len >= SNMP_TAG_SIZ)
179 return (SNMP_ERR_INCONS_VALUE);
180 ctx->scratch->int1 = strlen(addrs->taglist) + 1;
181 ctx->scratch->ptr1 = malloc(ctx->scratch->int1);
182 if (ctx->scratch->ptr1 == NULL)
183 return (SNMP_ERR_GENERR);
184 strlcpy(ctx->scratch->ptr1, addrs->taglist,
186 memcpy(addrs->taglist, val->v.octetstring.octets,
187 val->v.octetstring.len);
188 addrs->taglist[val->v.octetstring.len] = '\0';
191 case LEAF_snmpTargetAddrParams:
192 if (val->v.octetstring.len >= SNMP_ADM_STR32_SIZ)
193 return (SNMP_ERR_INCONS_VALUE);
194 ctx->scratch->int1 = strlen(addrs->paramname) + 1;
195 ctx->scratch->ptr1 = malloc(ctx->scratch->int1);
196 if (ctx->scratch->ptr1 == NULL)
197 return (SNMP_ERR_GENERR);
198 strlcpy(ctx->scratch->ptr1, addrs->paramname,
200 memcpy(addrs->paramname, val->v.octetstring.octets,
201 val->v.octetstring.len);
202 addrs->paramname[val->v.octetstring.len] = '\0';
205 case LEAF_snmpTargetAddrRetryCount:
206 ctx->scratch->int1 = addrs->retry;
207 addrs->retry = val->v.integer;
210 case LEAF_snmpTargetAddrTimeout:
211 ctx->scratch->int1 = addrs->timeout;
212 addrs->timeout = val->v.integer / 10;
215 case LEAF_snmpTargetAddrStorageType:
216 return (SNMP_ERR_INCONS_VALUE);
218 case LEAF_snmpTargetAddrRowStatus:
220 if (val->v.integer != RowStatus_active &&
221 val->v.integer != RowStatus_destroy)
222 return (SNMP_ERR_INCONS_VALUE);
223 if (val->v.integer == RowStatus_active &&
224 (addrs->address[0] == 0 ||
225 strlen(addrs->taglist) == 0 ||
226 strlen(addrs->paramname) == 0))
227 return (SNMP_ERR_INCONS_VALUE);
228 ctx->scratch->int1 = addrs->status;
229 addrs->status = val->v.integer;
230 return (SNMP_ERR_NOERROR);
232 if (val->v.integer != RowStatus_createAndWait ||
233 target_decode_index(&val->var, sub, aname) < 0)
234 return (SNMP_ERR_INCONS_VALUE);
235 if ((addrs = target_new_address(aname)) == NULL)
236 return (SNMP_ERR_GENERR);
237 addrs->status = RowStatus_destroy;
238 if (community != COMM_INITIALIZE)
239 addrs->type = StorageType_volatile;
241 addrs->type = StorageType_readOnly;
244 return (SNMP_ERR_NOERROR);
247 switch (val->var.subs[sub - 1]) {
248 case LEAF_snmpTargetAddrTAddress:
249 case LEAF_snmpTargetAddrTagList:
250 case LEAF_snmpTargetAddrParams:
251 free(ctx->scratch->ptr1);
253 case LEAF_snmpTargetAddrRowStatus:
254 if ((addrs = target_get_address(&val->var, sub)) == NULL)
255 return (SNMP_ERR_GENERR);
256 if (val->v.integer == RowStatus_destroy)
257 return (target_delete_address(addrs));
258 else if (val->v.integer == RowStatus_active)
259 return (target_activate_address(addrs));
264 return (SNMP_ERR_NOERROR);
266 case SNMP_OP_ROLLBACK:
267 if ((addrs = target_get_address(&val->var, sub)) == NULL)
268 return (SNMP_ERR_GENERR);
270 switch (val->var.subs[sub - 1]) {
271 case LEAF_snmpTargetAddrTAddress:
272 memcpy(addrs->address, ctx->scratch->ptr1,
274 free(ctx->scratch->ptr1);
277 case LEAF_snmpTargetAddrTagList:
278 strlcpy(addrs->taglist, ctx->scratch->ptr1,
280 free(ctx->scratch->ptr1);
283 case LEAF_snmpTargetAddrParams:
284 strlcpy(addrs->paramname, ctx->scratch->ptr1,
286 free(ctx->scratch->ptr1);
289 case LEAF_snmpTargetAddrRetryCount:
290 addrs->retry = ctx->scratch->int1;
293 case LEAF_snmpTargetAddrTimeout:
294 addrs->timeout = ctx->scratch->int1;
297 case LEAF_snmpTargetAddrRowStatus:
298 if (ctx->scratch->int1 == RowStatus_destroy)
299 return (target_delete_address(addrs));
309 switch (val->var.subs[sub - 1]) {
310 case LEAF_snmpTargetAddrTDomain:
311 return (oid_get(val, &oid_udp_domain));
312 case LEAF_snmpTargetAddrTAddress:
313 return (string_get(val, addrs->address, SNMP_UDP_ADDR_SIZ));
314 case LEAF_snmpTargetAddrTimeout:
315 val->v.integer = addrs->timeout;
317 case LEAF_snmpTargetAddrRetryCount:
318 val->v.integer = addrs->retry;
320 case LEAF_snmpTargetAddrTagList:
321 return (string_get(val, addrs->taglist, -1));
322 case LEAF_snmpTargetAddrParams:
323 return (string_get(val, addrs->paramname, -1));
324 case LEAF_snmpTargetAddrStorageType:
325 val->v.integer = addrs->type;
327 case LEAF_snmpTargetAddrRowStatus:
328 val->v.integer = addrs->status;
334 return (SNMP_ERR_NOERROR);
338 op_snmp_target_params(struct snmp_context *ctx __unused, struct snmp_value *val,
339 uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
341 char pname[SNMP_ADM_STR32_SIZ];
342 struct target_param *param;
346 if ((param = target_get_param(&val->var, sub)) == NULL)
347 return (SNMP_ERR_NOSUCHNAME);
350 case SNMP_OP_GETNEXT:
351 if ((param = target_get_next_param(&val->var, sub)) == NULL)
352 return (SNMP_ERR_NOSUCHNAME);
353 target_append_index(&val->var, sub, param->name);
357 if ((param = target_get_param(&val->var, sub)) == NULL &&
358 (val->var.subs[sub - 1] != LEAF_snmpTargetParamsRowStatus ||
359 val->v.integer != RowStatus_createAndWait))
360 return (SNMP_ERR_NOSUCHNAME);
363 if (community != COMM_INITIALIZE &&
364 param->type == StorageType_readOnly)
365 return (SNMP_ERR_NOT_WRITEABLE);
366 if (param->status == RowStatus_active &&
367 val->v.integer != RowStatus_destroy)
368 return (SNMP_ERR_INCONS_VALUE);
371 switch (val->var.subs[sub - 1]) {
372 case LEAF_snmpTargetParamsMPModel:
373 if (val->v.integer != SNMP_MPM_SNMP_V1 &&
374 val->v.integer != SNMP_MPM_SNMP_V2c &&
375 val->v.integer != SNMP_MPM_SNMP_V3)
376 return (SNMP_ERR_INCONS_VALUE);
377 ctx->scratch->int1 = param->mpmodel;
378 param->mpmodel = val->v.integer;
381 case LEAF_snmpTargetParamsSecurityModel:
382 if (val->v.integer != SNMP_SECMODEL_SNMPv1 &&
383 val->v.integer != SNMP_SECMODEL_SNMPv2c &&
384 val->v.integer != SNMP_SECMODEL_USM)
385 return (SNMP_ERR_INCONS_VALUE);
386 ctx->scratch->int1 = param->sec_model;
387 param->sec_model = val->v.integer;
390 case LEAF_snmpTargetParamsSecurityName:
391 if (val->v.octetstring.len >= SNMP_ADM_STR32_SIZ)
392 return (SNMP_ERR_INCONS_VALUE);
393 ctx->scratch->int1 = strlen(param->secname) + 1;
394 ctx->scratch->ptr1 = malloc(ctx->scratch->int1);
395 if (ctx->scratch->ptr1 == NULL)
396 return (SNMP_ERR_GENERR);
397 strlcpy(ctx->scratch->ptr1, param->secname,
399 memcpy(param->secname, val->v.octetstring.octets,
400 val->v.octetstring.len);
401 param->secname[val->v.octetstring.len] = '\0';
404 case LEAF_snmpTargetParamsSecurityLevel:
405 if (val->v.integer != SNMP_noAuthNoPriv &&
406 val->v.integer != SNMP_authNoPriv &&
407 val->v.integer != SNMP_authPriv)
408 return (SNMP_ERR_INCONS_VALUE);
409 ctx->scratch->int1 = param->sec_level;
410 param->sec_level = val->v.integer;
413 case LEAF_snmpTargetParamsStorageType:
414 return (SNMP_ERR_INCONS_VALUE);
416 case LEAF_snmpTargetParamsRowStatus:
418 if (val->v.integer != RowStatus_active &&
419 val->v.integer != RowStatus_destroy)
420 return (SNMP_ERR_INCONS_VALUE);
421 if (val->v.integer == RowStatus_active &&
422 (param->sec_model == 0 ||
423 param->sec_level == 0 ||
424 strlen(param->secname) == 0))
425 return (SNMP_ERR_INCONS_VALUE);
426 ctx->scratch->int1 = param->status;
427 param->status = val->v.integer;
428 return (SNMP_ERR_NOERROR);
430 if (val->v.integer != RowStatus_createAndWait ||
431 target_decode_index(&val->var, sub, pname) < 0)
432 return (SNMP_ERR_INCONS_VALUE);
433 if ((param = target_new_param(pname)) == NULL)
434 return (SNMP_ERR_GENERR);
435 param->status = RowStatus_destroy;
436 if (community != COMM_INITIALIZE)
437 param->type = StorageType_volatile;
439 param->type = StorageType_readOnly;
442 return (SNMP_ERR_NOERROR);
445 switch (val->var.subs[sub - 1]) {
446 case LEAF_snmpTargetParamsSecurityName:
447 free(ctx->scratch->ptr1);
449 case LEAF_snmpTargetParamsRowStatus:
450 if ((param = target_get_param(&val->var, sub)) == NULL)
451 return (SNMP_ERR_GENERR);
452 if (val->v.integer == RowStatus_destroy)
453 return (target_delete_param(param));
458 return (SNMP_ERR_NOERROR);
460 case SNMP_OP_ROLLBACK:
461 if ((param = target_get_param(&val->var, sub)) == NULL &&
462 (val->var.subs[sub - 1] != LEAF_snmpTargetParamsRowStatus ||
463 val->v.integer != RowStatus_createAndWait))
464 return (SNMP_ERR_GENERR);
465 switch (val->var.subs[sub - 1]) {
466 case LEAF_snmpTargetParamsMPModel:
467 param->mpmodel = ctx->scratch->int1;
469 case LEAF_snmpTargetParamsSecurityModel:
470 param->sec_model = ctx->scratch->int1;
472 case LEAF_snmpTargetParamsSecurityName:
473 strlcpy(param->secname, ctx->scratch->ptr1,
474 sizeof(param->secname));
475 free(ctx->scratch->ptr1);
477 case LEAF_snmpTargetParamsSecurityLevel:
478 param->sec_level = ctx->scratch->int1;
480 case LEAF_snmpTargetParamsRowStatus:
481 if (ctx->scratch->int1 == RowStatus_destroy)
482 return (target_delete_param(param));
488 return (SNMP_ERR_NOERROR);
494 switch (val->var.subs[sub - 1]) {
495 case LEAF_snmpTargetParamsMPModel:
496 val->v.integer = param->mpmodel;
498 case LEAF_snmpTargetParamsSecurityModel:
499 val->v.integer = param->sec_model;
501 case LEAF_snmpTargetParamsSecurityName:
502 return (string_get(val, param->secname, -1));
503 case LEAF_snmpTargetParamsSecurityLevel:
504 val->v.integer = param->sec_level;
506 case LEAF_snmpTargetParamsStorageType:
507 val->v.integer = param->type;
509 case LEAF_snmpTargetParamsRowStatus:
510 val->v.integer = param->status;
516 return (SNMP_ERR_NOERROR);
520 op_snmp_notify(struct snmp_context *ctx __unused, struct snmp_value *val,
521 uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
523 char nname[SNMP_ADM_STR32_SIZ];
524 struct target_notify *notify;
528 if ((notify = target_get_notify(&val->var, sub)) == NULL)
529 return (SNMP_ERR_NOSUCHNAME);
532 case SNMP_OP_GETNEXT:
533 if ((notify = target_get_next_notify(&val->var, sub)) == NULL)
534 return (SNMP_ERR_NOSUCHNAME);
535 target_append_index(&val->var, sub, notify->name);
539 if ((notify = target_get_notify(&val->var, sub)) == NULL &&
540 (val->var.subs[sub - 1] != LEAF_snmpNotifyRowStatus ||
541 val->v.integer != RowStatus_createAndGo))
542 return (SNMP_ERR_NOSUCHNAME);
544 if (notify != NULL) {
545 if (community != COMM_INITIALIZE &&
546 notify->type == StorageType_readOnly)
547 return (SNMP_ERR_NOT_WRITEABLE);
550 switch (val->var.subs[sub - 1]) {
551 case LEAF_snmpNotifyTag:
552 if (val->v.octetstring.len >= SNMP_TAG_SIZ)
553 return (SNMP_ERR_INCONS_VALUE);
554 ctx->scratch->int1 = strlen(notify->taglist) + 1;
555 ctx->scratch->ptr1 = malloc(ctx->scratch->int1);
556 if (ctx->scratch->ptr1 == NULL)
557 return (SNMP_ERR_GENERR);
558 strlcpy(ctx->scratch->ptr1, notify->taglist,
560 memcpy(notify->taglist, val->v.octetstring.octets,
561 val->v.octetstring.len);
562 notify->taglist[val->v.octetstring.len] = '\0';
565 case LEAF_snmpNotifyType:
567 case LEAF_snmpNotifyStorageType:
568 return (SNMP_ERR_INCONS_VALUE);
569 case LEAF_snmpNotifyRowStatus:
570 if (notify != NULL) {
571 if (val->v.integer != RowStatus_active &&
572 val->v.integer != RowStatus_destroy)
573 return (SNMP_ERR_INCONS_VALUE);
574 ctx->scratch->int1 = notify->status;
575 notify->status = val->v.integer;
576 return (SNMP_ERR_NOERROR);
578 if (val->v.integer != RowStatus_createAndGo ||
579 target_decode_index(&val->var, sub, nname) < 0)
580 return (SNMP_ERR_INCONS_VALUE);
581 if ((notify = target_new_notify(nname)) == NULL)
582 return (SNMP_ERR_GENERR);
583 notify->status = RowStatus_destroy;
584 if (community != COMM_INITIALIZE)
585 notify->type = StorageType_volatile;
587 notify->type = StorageType_readOnly;
590 return (SNMP_ERR_NOERROR);
593 switch (val->var.subs[sub - 1]) {
594 case LEAF_snmpNotifyTag:
595 free(ctx->scratch->ptr1);
597 case LEAF_snmpNotifyRowStatus:
598 notify = target_get_notify(&val->var, sub);
600 return (SNMP_ERR_GENERR);
601 if (val->v.integer == RowStatus_destroy)
602 return (target_delete_notify(notify));
604 notify->status = RowStatus_active;
609 return (SNMP_ERR_NOERROR);
611 case SNMP_OP_ROLLBACK:
612 if ((notify = target_get_notify(&val->var, sub)) == NULL)
613 return (SNMP_ERR_GENERR);
615 switch (val->var.subs[sub - 1]) {
616 case LEAF_snmpNotifyTag:
617 strlcpy(notify->taglist, ctx->scratch->ptr1,
619 free(ctx->scratch->ptr1);
621 case LEAF_snmpNotifyRowStatus:
622 if (ctx->scratch->int1 == RowStatus_destroy)
623 return (target_delete_notify(notify));
634 switch (val->var.subs[sub - 1]) {
635 case LEAF_snmpNotifyTag:
636 return (string_get(val, notify->taglist, -1));
637 case LEAF_snmpNotifyType:
638 val->v.integer = snmpNotifyType_trap;
640 case LEAF_snmpNotifyStorageType:
641 val->v.integer = notify->type;
643 case LEAF_snmpNotifyRowStatus:
644 val->v.integer = notify->status;
650 return (SNMP_ERR_NOERROR);
654 target_append_index(struct asn_oid *oid, uint sub, const char *name)
658 oid->len = sub + strlen(name);
659 for (i = 0; i < strlen(name); i++)
660 oid->subs[sub + i] = name[i];
664 target_decode_index(const struct asn_oid *oid, uint sub, char *name)
668 if ((len = oid->len - sub) >= SNMP_ADM_STR32_SIZ)
671 for (i = 0; i < len; i++)
672 name[i] = oid->subs[sub + i];
678 static struct target_address *
679 target_get_address(const struct asn_oid *oid, uint sub)
681 char aname[SNMP_ADM_STR32_SIZ];
682 struct target_address *addrs;
684 if (target_decode_index(oid, sub, aname) < 0)
687 for (addrs = target_first_address(); addrs != NULL;
688 addrs = target_next_address(addrs))
689 if (strcmp(aname, addrs->name) == 0)
695 static struct target_address *
696 target_get_next_address(const struct asn_oid * oid, uint sub)
698 char aname[SNMP_ADM_STR32_SIZ];
699 struct target_address *addrs;
701 if (oid->len - sub == 0)
702 return (target_first_address());
704 if (target_decode_index(oid, sub, aname) < 0)
707 for (addrs = target_first_address(); addrs != NULL;
708 addrs = target_next_address(addrs))
709 if (strcmp(aname, addrs->name) == 0)
710 return (target_next_address(addrs));
715 static struct target_param *
716 target_get_param(const struct asn_oid *oid, uint sub)
718 char pname[SNMP_ADM_STR32_SIZ];
719 struct target_param *param;
721 if (target_decode_index(oid, sub, pname) < 0)
724 for (param = target_first_param(); param != NULL;
725 param = target_next_param(param))
726 if (strcmp(pname, param->name) == 0)
732 static struct target_param *
733 target_get_next_param(const struct asn_oid *oid, uint sub)
735 char pname[SNMP_ADM_STR32_SIZ];
736 struct target_param *param;
738 if (oid->len - sub == 0)
739 return (target_first_param());
741 if (target_decode_index(oid, sub, pname) < 0)
744 for (param = target_first_param(); param != NULL;
745 param = target_next_param(param))
746 if (strcmp(pname, param->name) == 0)
747 return (target_next_param(param));
752 static struct target_notify *
753 target_get_notify(const struct asn_oid *oid, uint sub)
755 char nname[SNMP_ADM_STR32_SIZ];
756 struct target_notify *notify;
758 if (target_decode_index(oid, sub, nname) < 0)
761 for (notify = target_first_notify(); notify != NULL;
762 notify = target_next_notify(notify))
763 if (strcmp(nname, notify->name) == 0)
769 static struct target_notify *
770 target_get_next_notify(const struct asn_oid *oid, uint sub)
772 char nname[SNMP_ADM_STR32_SIZ];
773 struct target_notify *notify;
775 if (oid->len - sub == 0)
776 return (target_first_notify());
778 if (target_decode_index(oid, sub, nname) < 0)
781 for (notify = target_first_notify(); notify != NULL;
782 notify = target_next_notify(notify))
783 if (strcmp(nname, notify->name) == 0)
784 return (target_next_notify(notify));
790 target_init(struct lmodule *mod, int argc __unused, char *argv[] __unused)
793 target_lock = random();
803 or_unregister(reg_target);
804 or_unregister(reg_notification);
812 reg_target = or_register(&oid_target,
813 "The MIB module for managing SNMP Management Targets.",
815 reg_notification = or_register(&oid_notification,
816 "The MIB module for configuring generation of SNMP notifications.",
823 /* XXX: dump the module stats & list of mgmt targets */
826 const char target_comment[] = \
827 "This module implements SNMP Management Target MIB Module defined in RFC 3413.";
829 const struct snmp_module config = {
830 .comment = target_comment,
833 .start = target_start,
834 .tree = target_ctree,
836 .tree_size = target_CTREE_SIZE,