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));
304 return (SNMP_ERR_NOERROR);
310 switch (val->var.subs[sub - 1]) {
311 case LEAF_snmpTargetAddrTDomain:
312 return (oid_get(val, &oid_udp_domain));
313 case LEAF_snmpTargetAddrTAddress:
314 return (string_get(val, addrs->address, SNMP_UDP_ADDR_SIZ));
315 case LEAF_snmpTargetAddrTimeout:
316 val->v.integer = addrs->timeout;
318 case LEAF_snmpTargetAddrRetryCount:
319 val->v.integer = addrs->retry;
321 case LEAF_snmpTargetAddrTagList:
322 return (string_get(val, addrs->taglist, -1));
323 case LEAF_snmpTargetAddrParams:
324 return (string_get(val, addrs->paramname, -1));
325 case LEAF_snmpTargetAddrStorageType:
326 val->v.integer = addrs->type;
328 case LEAF_snmpTargetAddrRowStatus:
329 val->v.integer = addrs->status;
335 return (SNMP_ERR_NOERROR);
339 op_snmp_target_params(struct snmp_context *ctx __unused, struct snmp_value *val,
340 uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
342 char pname[SNMP_ADM_STR32_SIZ];
343 struct target_param *param;
347 if ((param = target_get_param(&val->var, sub)) == NULL)
348 return (SNMP_ERR_NOSUCHNAME);
351 case SNMP_OP_GETNEXT:
352 if ((param = target_get_next_param(&val->var, sub)) == NULL)
353 return (SNMP_ERR_NOSUCHNAME);
354 target_append_index(&val->var, sub, param->name);
358 if ((param = target_get_param(&val->var, sub)) == NULL &&
359 (val->var.subs[sub - 1] != LEAF_snmpTargetParamsRowStatus ||
360 val->v.integer != RowStatus_createAndWait))
361 return (SNMP_ERR_NOSUCHNAME);
364 if (community != COMM_INITIALIZE &&
365 param->type == StorageType_readOnly)
366 return (SNMP_ERR_NOT_WRITEABLE);
367 if (param->status == RowStatus_active &&
368 val->v.integer != RowStatus_destroy)
369 return (SNMP_ERR_INCONS_VALUE);
372 switch (val->var.subs[sub - 1]) {
373 case LEAF_snmpTargetParamsMPModel:
374 if (val->v.integer != SNMP_MPM_SNMP_V1 &&
375 val->v.integer != SNMP_MPM_SNMP_V2c &&
376 val->v.integer != SNMP_MPM_SNMP_V3)
377 return (SNMP_ERR_INCONS_VALUE);
378 ctx->scratch->int1 = param->mpmodel;
379 param->mpmodel = val->v.integer;
382 case LEAF_snmpTargetParamsSecurityModel:
383 if (val->v.integer != SNMP_SECMODEL_SNMPv1 &&
384 val->v.integer != SNMP_SECMODEL_SNMPv2c &&
385 val->v.integer != SNMP_SECMODEL_USM)
386 return (SNMP_ERR_INCONS_VALUE);
387 ctx->scratch->int1 = param->sec_model;
388 param->sec_model = val->v.integer;
391 case LEAF_snmpTargetParamsSecurityName:
392 if (val->v.octetstring.len >= SNMP_ADM_STR32_SIZ)
393 return (SNMP_ERR_INCONS_VALUE);
394 ctx->scratch->int1 = strlen(param->secname) + 1;
395 ctx->scratch->ptr1 = malloc(ctx->scratch->int1);
396 if (ctx->scratch->ptr1 == NULL)
397 return (SNMP_ERR_GENERR);
398 strlcpy(ctx->scratch->ptr1, param->secname,
400 memcpy(param->secname, val->v.octetstring.octets,
401 val->v.octetstring.len);
402 param->secname[val->v.octetstring.len] = '\0';
405 case LEAF_snmpTargetParamsSecurityLevel:
406 if (val->v.integer != SNMP_noAuthNoPriv &&
407 val->v.integer != SNMP_authNoPriv &&
408 val->v.integer != SNMP_authPriv)
409 return (SNMP_ERR_INCONS_VALUE);
410 ctx->scratch->int1 = param->sec_level;
411 param->sec_level = val->v.integer;
414 case LEAF_snmpTargetParamsStorageType:
415 return (SNMP_ERR_INCONS_VALUE);
417 case LEAF_snmpTargetParamsRowStatus:
419 if (val->v.integer != RowStatus_active &&
420 val->v.integer != RowStatus_destroy)
421 return (SNMP_ERR_INCONS_VALUE);
422 if (val->v.integer == RowStatus_active &&
423 (param->sec_model == 0 ||
424 param->sec_level == 0 ||
425 strlen(param->secname) == 0))
426 return (SNMP_ERR_INCONS_VALUE);
427 ctx->scratch->int1 = param->status;
428 param->status = val->v.integer;
429 return (SNMP_ERR_NOERROR);
431 if (val->v.integer != RowStatus_createAndWait ||
432 target_decode_index(&val->var, sub, pname) < 0)
433 return (SNMP_ERR_INCONS_VALUE);
434 if ((param = target_new_param(pname)) == NULL)
435 return (SNMP_ERR_GENERR);
436 param->status = RowStatus_destroy;
437 if (community != COMM_INITIALIZE)
438 param->type = StorageType_volatile;
440 param->type = StorageType_readOnly;
443 return (SNMP_ERR_NOERROR);
446 switch (val->var.subs[sub - 1]) {
447 case LEAF_snmpTargetParamsSecurityName:
448 free(ctx->scratch->ptr1);
450 case LEAF_snmpTargetParamsRowStatus:
451 if ((param = target_get_param(&val->var, sub)) == NULL)
452 return (SNMP_ERR_GENERR);
453 if (val->v.integer == RowStatus_destroy)
454 return (target_delete_param(param));
459 return (SNMP_ERR_NOERROR);
461 case SNMP_OP_ROLLBACK:
462 if ((param = target_get_param(&val->var, sub)) == NULL &&
463 (val->var.subs[sub - 1] != LEAF_snmpTargetParamsRowStatus ||
464 val->v.integer != RowStatus_createAndWait))
465 return (SNMP_ERR_GENERR);
466 switch (val->var.subs[sub - 1]) {
467 case LEAF_snmpTargetParamsMPModel:
468 param->mpmodel = ctx->scratch->int1;
470 case LEAF_snmpTargetParamsSecurityModel:
471 param->sec_model = ctx->scratch->int1;
473 case LEAF_snmpTargetParamsSecurityName:
474 strlcpy(param->secname, ctx->scratch->ptr1,
475 sizeof(param->secname));
476 free(ctx->scratch->ptr1);
478 case LEAF_snmpTargetParamsSecurityLevel:
479 param->sec_level = ctx->scratch->int1;
481 case LEAF_snmpTargetParamsRowStatus:
482 if (ctx->scratch->int1 == RowStatus_destroy)
483 return (target_delete_param(param));
489 return (SNMP_ERR_NOERROR);
495 switch (val->var.subs[sub - 1]) {
496 case LEAF_snmpTargetParamsMPModel:
497 val->v.integer = param->mpmodel;
499 case LEAF_snmpTargetParamsSecurityModel:
500 val->v.integer = param->sec_model;
502 case LEAF_snmpTargetParamsSecurityName:
503 return (string_get(val, param->secname, -1));
504 case LEAF_snmpTargetParamsSecurityLevel:
505 val->v.integer = param->sec_level;
507 case LEAF_snmpTargetParamsStorageType:
508 val->v.integer = param->type;
510 case LEAF_snmpTargetParamsRowStatus:
511 val->v.integer = param->status;
517 return (SNMP_ERR_NOERROR);
521 op_snmp_notify(struct snmp_context *ctx __unused, struct snmp_value *val,
522 uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
524 char nname[SNMP_ADM_STR32_SIZ];
525 struct target_notify *notify;
529 if ((notify = target_get_notify(&val->var, sub)) == NULL)
530 return (SNMP_ERR_NOSUCHNAME);
533 case SNMP_OP_GETNEXT:
534 if ((notify = target_get_next_notify(&val->var, sub)) == NULL)
535 return (SNMP_ERR_NOSUCHNAME);
536 target_append_index(&val->var, sub, notify->name);
540 if ((notify = target_get_notify(&val->var, sub)) == NULL &&
541 (val->var.subs[sub - 1] != LEAF_snmpNotifyRowStatus ||
542 val->v.integer != RowStatus_createAndGo))
543 return (SNMP_ERR_NOSUCHNAME);
545 if (notify != NULL) {
546 if (community != COMM_INITIALIZE &&
547 notify->type == StorageType_readOnly)
548 return (SNMP_ERR_NOT_WRITEABLE);
551 switch (val->var.subs[sub - 1]) {
552 case LEAF_snmpNotifyTag:
553 if (val->v.octetstring.len >= SNMP_TAG_SIZ)
554 return (SNMP_ERR_INCONS_VALUE);
555 ctx->scratch->int1 = strlen(notify->taglist) + 1;
556 ctx->scratch->ptr1 = malloc(ctx->scratch->int1);
557 if (ctx->scratch->ptr1 == NULL)
558 return (SNMP_ERR_GENERR);
559 strlcpy(ctx->scratch->ptr1, notify->taglist,
561 memcpy(notify->taglist, val->v.octetstring.octets,
562 val->v.octetstring.len);
563 notify->taglist[val->v.octetstring.len] = '\0';
566 case LEAF_snmpNotifyType:
568 case LEAF_snmpNotifyStorageType:
569 return (SNMP_ERR_INCONS_VALUE);
570 case LEAF_snmpNotifyRowStatus:
571 if (notify != NULL) {
572 if (val->v.integer != RowStatus_active &&
573 val->v.integer != RowStatus_destroy)
574 return (SNMP_ERR_INCONS_VALUE);
575 ctx->scratch->int1 = notify->status;
576 notify->status = val->v.integer;
577 return (SNMP_ERR_NOERROR);
579 if (val->v.integer != RowStatus_createAndGo ||
580 target_decode_index(&val->var, sub, nname) < 0)
581 return (SNMP_ERR_INCONS_VALUE);
582 if ((notify = target_new_notify(nname)) == NULL)
583 return (SNMP_ERR_GENERR);
584 notify->status = RowStatus_destroy;
585 if (community != COMM_INITIALIZE)
586 notify->type = StorageType_volatile;
588 notify->type = StorageType_readOnly;
591 return (SNMP_ERR_NOERROR);
594 switch (val->var.subs[sub - 1]) {
595 case LEAF_snmpNotifyTag:
596 free(ctx->scratch->ptr1);
598 case LEAF_snmpNotifyRowStatus:
599 notify = target_get_notify(&val->var, sub);
601 return (SNMP_ERR_GENERR);
602 if (val->v.integer == RowStatus_destroy)
603 return (target_delete_notify(notify));
605 notify->status = RowStatus_active;
610 return (SNMP_ERR_NOERROR);
612 case SNMP_OP_ROLLBACK:
613 if ((notify = target_get_notify(&val->var, sub)) == NULL)
614 return (SNMP_ERR_GENERR);
616 switch (val->var.subs[sub - 1]) {
617 case LEAF_snmpNotifyTag:
618 strlcpy(notify->taglist, ctx->scratch->ptr1,
620 free(ctx->scratch->ptr1);
622 case LEAF_snmpNotifyRowStatus:
623 if (ctx->scratch->int1 == RowStatus_destroy)
624 return (target_delete_notify(notify));
629 return (SNMP_ERR_NOERROR);
636 switch (val->var.subs[sub - 1]) {
637 case LEAF_snmpNotifyTag:
638 return (string_get(val, notify->taglist, -1));
639 case LEAF_snmpNotifyType:
640 val->v.integer = snmpNotifyType_trap;
642 case LEAF_snmpNotifyStorageType:
643 val->v.integer = notify->type;
645 case LEAF_snmpNotifyRowStatus:
646 val->v.integer = notify->status;
652 return (SNMP_ERR_NOERROR);
656 target_append_index(struct asn_oid *oid, uint sub, const char *name)
660 oid->len = sub + strlen(name);
661 for (i = 0; i < strlen(name); i++)
662 oid->subs[sub + i] = name[i];
666 target_decode_index(const struct asn_oid *oid, uint sub, char *name)
670 if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >=
674 for (i = 0; i < oid->subs[sub]; i++)
675 name[i] = oid->subs[sub + i + 1];
681 static struct target_address *
682 target_get_address(const struct asn_oid *oid, uint sub)
684 char aname[SNMP_ADM_STR32_SIZ];
685 struct target_address *addrs;
687 if (target_decode_index(oid, sub, aname) < 0)
690 for (addrs = target_first_address(); addrs != NULL;
691 addrs = target_next_address(addrs))
692 if (strcmp(aname, addrs->name) == 0)
698 static struct target_address *
699 target_get_next_address(const struct asn_oid * oid, uint sub)
701 char aname[SNMP_ADM_STR32_SIZ];
702 struct target_address *addrs;
704 if (oid->len - sub == 0)
705 return (target_first_address());
707 if (target_decode_index(oid, sub, aname) < 0)
710 for (addrs = target_first_address(); addrs != NULL;
711 addrs = target_next_address(addrs))
712 if (strcmp(aname, addrs->name) == 0)
713 return (target_next_address(addrs));
718 static struct target_param *
719 target_get_param(const struct asn_oid *oid, uint sub)
721 char pname[SNMP_ADM_STR32_SIZ];
722 struct target_param *param;
724 if (target_decode_index(oid, sub, pname) < 0)
727 for (param = target_first_param(); param != NULL;
728 param = target_next_param(param))
729 if (strcmp(pname, param->name) == 0)
735 static struct target_param *
736 target_get_next_param(const struct asn_oid *oid, uint sub)
738 char pname[SNMP_ADM_STR32_SIZ];
739 struct target_param *param;
741 if (oid->len - sub == 0)
742 return (target_first_param());
744 if (target_decode_index(oid, sub, pname) < 0)
747 for (param = target_first_param(); param != NULL;
748 param = target_next_param(param))
749 if (strcmp(pname, param->name) == 0)
750 return (target_next_param(param));
755 static struct target_notify *
756 target_get_notify(const struct asn_oid *oid, uint sub)
758 char nname[SNMP_ADM_STR32_SIZ];
759 struct target_notify *notify;
761 if (target_decode_index(oid, sub, nname) < 0)
764 for (notify = target_first_notify(); notify != NULL;
765 notify = target_next_notify(notify))
766 if (strcmp(nname, notify->name) == 0)
772 static struct target_notify *
773 target_get_next_notify(const struct asn_oid *oid, uint sub)
775 char nname[SNMP_ADM_STR32_SIZ];
776 struct target_notify *notify;
778 if (oid->len - sub == 0)
779 return (target_first_notify());
781 if (target_decode_index(oid, sub, nname) < 0)
784 for (notify = target_first_notify(); notify != NULL;
785 notify = target_next_notify(notify))
786 if (strcmp(nname, notify->name) == 0)
787 return (target_next_notify(notify));
793 target_init(struct lmodule *mod, int argc __unused, char *argv[] __unused)
796 target_lock = random();
806 or_unregister(reg_target);
807 or_unregister(reg_notification);
815 reg_target = or_register(&oid_target,
816 "The MIB module for managing SNMP Management Targets.",
818 reg_notification = or_register(&oid_notification,
819 "The MIB module for configuring generation of SNMP notifications.",
826 /* XXX: dump the module stats & list of mgmt targets */
829 const char target_comment[] = \
830 "This module implements SNMP Management Target MIB Module defined in RFC 3413.";
832 const struct snmp_module config = {
833 .comment = target_comment,
836 .start = target_start,
837 .tree = target_ctree,
839 .tree_size = target_CTREE_SIZE,