1 /*- 2 * Copyright (c) 2010 The FreeBSD Foundation 3 * All rights reserved. 4 * 5 * This software was developed by Shteryana Sotirova Shopova under 6 * sponsorship from the FreeBSD Foundation. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 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. 16 * 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 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD$ 30 */ 31 #include <sys/queue.h> 32 #include <sys/types.h> 33 34 #include <errno.h> 35 #include <stdarg.h> 36 #include <stdlib.h> 37 #include <stdio.h> 38 #include <stdint.h> 39 #include <string.h> 40 #include <syslog.h> 41 42 #include "asn1.h" 43 #include "snmp.h" 44 #include "snmpmod.h" 45 46 #include "target_tree.h" 47 #include "target_oid.h" 48 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; 53 54 static uint reg_target; 55 static uint reg_notification; 56 57 static int32_t target_lock; 58 59 static const struct asn_oid oid_udp_domain = OIDX_snmpUDPDomain; 60 61 /* 62 * Internal datastructures and forward declarations. 63 */ 64 static void target_append_index(struct asn_oid *, uint, 65 const char *); 66 static int target_decode_index(const struct asn_oid *, uint, 67 char *); 68 static struct target_address *target_get_address(const struct asn_oid *, 69 uint); 70 static struct target_address *target_get_next_address(const struct asn_oid *, 71 uint); 72 static struct target_param *target_get_param(const struct asn_oid *, 73 uint); 74 static struct target_param *target_get_next_param(const struct asn_oid *, 75 uint); 76 static struct target_notify *target_get_notify(const struct asn_oid *, 77 uint); 78 static struct target_notify *target_get_next_notify(const struct asn_oid *, 79 uint); 80 81 int 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) 84 { 85 struct snmpd_target_stats *ctx_stats; 86 87 if (val->var.subs[sub - 1] == LEAF_snmpTargetSpinLock) { 88 switch (op) { 89 case SNMP_OP_GET: 90 if (++target_lock == INT32_MAX) 91 target_lock = 0; 92 val->v.integer = target_lock; 93 break; 94 case SNMP_OP_GETNEXT: 95 abort(); 96 case SNMP_OP_SET: 97 if (val->v.integer != target_lock) 98 return (SNMP_ERR_INCONS_VALUE); 99 break; 100 case SNMP_OP_ROLLBACK: 101 /* FALLTHROUGH */ 102 case SNMP_OP_COMMIT: 103 break; 104 } 105 return (SNMP_ERR_NOERROR); 106 } else if (op == SNMP_OP_SET) 107 return (SNMP_ERR_NOT_WRITEABLE); 108 109 if ((ctx_stats = bsnmpd_get_target_stats()) == NULL) 110 return (SNMP_ERR_GENERR); 111 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; 116 break; 117 case LEAF_snmpUnknownContexts: 118 val->v.uint32 = ctx_stats->unknown_contexts; 119 break; 120 default: 121 return (SNMP_ERR_NOSUCHNAME); 122 } 123 return (SNMP_ERR_NOERROR); 124 } 125 abort(); 126 } 127 128 int 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) 131 { 132 char aname[SNMP_ADM_STR32_SIZ]; 133 struct target_address *addrs; 134 135 switch (op) { 136 case SNMP_OP_GET: 137 if ((addrs = target_get_address(&val->var, sub)) == NULL) 138 return (SNMP_ERR_NOSUCHNAME); 139 break; 140 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); 145 break; 146 147 case SNMP_OP_SET: 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); 152 153 if (addrs != NULL) { 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); 160 } 161 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, 172 SNMP_UDP_ADDR_SIZ); 173 memcpy(addrs->address, val->v.octetstring.octets, 174 SNMP_UDP_ADDR_SIZ); 175 break; 176 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, 185 ctx->scratch->int1); 186 memcpy(addrs->taglist, val->v.octetstring.octets, 187 val->v.octetstring.len); 188 addrs->taglist[val->v.octetstring.len] = '\0'; 189 break; 190 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, 199 ctx->scratch->int1); 200 memcpy(addrs->paramname, val->v.octetstring.octets, 201 val->v.octetstring.len); 202 addrs->paramname[val->v.octetstring.len] = '\0'; 203 break; 204 205 case LEAF_snmpTargetAddrRetryCount: 206 ctx->scratch->int1 = addrs->retry; 207 addrs->retry = val->v.integer; 208 break; 209 210 case LEAF_snmpTargetAddrTimeout: 211 ctx->scratch->int1 = addrs->timeout; 212 addrs->timeout = val->v.integer / 10; 213 break; 214 215 case LEAF_snmpTargetAddrStorageType: 216 return (SNMP_ERR_INCONS_VALUE); 217 218 case LEAF_snmpTargetAddrRowStatus: 219 if (addrs != NULL) { 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); 231 } 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; 240 else 241 addrs->type = StorageType_readOnly; 242 break; 243 } 244 return (SNMP_ERR_NOERROR); 245 246 case SNMP_OP_COMMIT: 247 switch (val->var.subs[sub - 1]) { 248 case LEAF_snmpTargetAddrTAddress: 249 case LEAF_snmpTargetAddrTagList: 250 case LEAF_snmpTargetAddrParams: 251 free(ctx->scratch->ptr1); 252 break; 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)); 260 break; 261 default: 262 break; 263 } 264 return (SNMP_ERR_NOERROR); 265 266 case SNMP_OP_ROLLBACK: 267 if ((addrs = target_get_address(&val->var, sub)) == NULL) 268 return (SNMP_ERR_GENERR); 269 270 switch (val->var.subs[sub - 1]) { 271 case LEAF_snmpTargetAddrTAddress: 272 memcpy(addrs->address, ctx->scratch->ptr1, 273 SNMP_UDP_ADDR_SIZ); 274 free(ctx->scratch->ptr1); 275 break; 276 277 case LEAF_snmpTargetAddrTagList: 278 strlcpy(addrs->taglist, ctx->scratch->ptr1, 279 ctx->scratch->int1); 280 free(ctx->scratch->ptr1); 281 break; 282 283 case LEAF_snmpTargetAddrParams: 284 strlcpy(addrs->paramname, ctx->scratch->ptr1, 285 ctx->scratch->int1); 286 free(ctx->scratch->ptr1); 287 break; 288 289 case LEAF_snmpTargetAddrRetryCount: 290 addrs->retry = ctx->scratch->int1; 291 break; 292 293 case LEAF_snmpTargetAddrTimeout: 294 addrs->timeout = ctx->scratch->int1; 295 break; 296 297 case LEAF_snmpTargetAddrRowStatus: 298 if (ctx->scratch->int1 == RowStatus_destroy) 299 return (target_delete_address(addrs)); 300 break; 301 default: 302 break; 303 } 304 305 default: 306 abort(); 307 } 308 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; 316 break; 317 case LEAF_snmpTargetAddrRetryCount: 318 val->v.integer = addrs->retry; 319 break; 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; 326 break; 327 case LEAF_snmpTargetAddrRowStatus: 328 val->v.integer = addrs->status; 329 break; 330 default: 331 abort(); 332 } 333 334 return (SNMP_ERR_NOERROR); 335 } 336 337 int 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) 340 { 341 char pname[SNMP_ADM_STR32_SIZ]; 342 struct target_param *param; 343 344 switch (op) { 345 case SNMP_OP_GET: 346 if ((param = target_get_param(&val->var, sub)) == NULL) 347 return (SNMP_ERR_NOSUCHNAME); 348 break; 349 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); 354 break; 355 356 case SNMP_OP_SET: 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); 361 362 if (param != NULL) { 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); 369 } 370 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; 379 break; 380 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; 388 break; 389 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, 398 ctx->scratch->int1); 399 memcpy(param->secname, val->v.octetstring.octets, 400 val->v.octetstring.len); 401 param->secname[val->v.octetstring.len] = '\0'; 402 break; 403 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; 411 break; 412 413 case LEAF_snmpTargetParamsStorageType: 414 return (SNMP_ERR_INCONS_VALUE); 415 416 case LEAF_snmpTargetParamsRowStatus: 417 if (param != NULL) { 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); 429 } 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; 438 else 439 param->type = StorageType_readOnly; 440 break; 441 } 442 return (SNMP_ERR_NOERROR); 443 444 case SNMP_OP_COMMIT: 445 switch (val->var.subs[sub - 1]) { 446 case LEAF_snmpTargetParamsSecurityName: 447 free(ctx->scratch->ptr1); 448 break; 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)); 454 break; 455 default: 456 break; 457 } 458 return (SNMP_ERR_NOERROR); 459 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; 468 break; 469 case LEAF_snmpTargetParamsSecurityModel: 470 param->sec_model = ctx->scratch->int1; 471 break; 472 case LEAF_snmpTargetParamsSecurityName: 473 strlcpy(param->secname, ctx->scratch->ptr1, 474 sizeof(param->secname)); 475 free(ctx->scratch->ptr1); 476 break; 477 case LEAF_snmpTargetParamsSecurityLevel: 478 param->sec_level = ctx->scratch->int1; 479 break; 480 case LEAF_snmpTargetParamsRowStatus: 481 if (ctx->scratch->int1 == RowStatus_destroy) 482 return (target_delete_param(param)); 483 break; 484 default: 485 break; 486 } 487 488 return (SNMP_ERR_NOERROR); 489 490 default: 491 abort(); 492 } 493 494 switch (val->var.subs[sub - 1]) { 495 case LEAF_snmpTargetParamsMPModel: 496 val->v.integer = param->mpmodel; 497 break; 498 case LEAF_snmpTargetParamsSecurityModel: 499 val->v.integer = param->sec_model; 500 break; 501 case LEAF_snmpTargetParamsSecurityName: 502 return (string_get(val, param->secname, -1)); 503 case LEAF_snmpTargetParamsSecurityLevel: 504 val->v.integer = param->sec_level; 505 break; 506 case LEAF_snmpTargetParamsStorageType: 507 val->v.integer = param->type; 508 break; 509 case LEAF_snmpTargetParamsRowStatus: 510 val->v.integer = param->status; 511 break; 512 default: 513 abort(); 514 } 515 516 return (SNMP_ERR_NOERROR); 517 } 518 519 int 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) 522 { 523 char nname[SNMP_ADM_STR32_SIZ]; 524 struct target_notify *notify; 525 526 switch (op) { 527 case SNMP_OP_GET: 528 if ((notify = target_get_notify(&val->var, sub)) == NULL) 529 return (SNMP_ERR_NOSUCHNAME); 530 break; 531 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); 536 break; 537 538 case SNMP_OP_SET: 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); 543 544 if (notify != NULL) { 545 if (community != COMM_INITIALIZE && 546 notify->type == StorageType_readOnly) 547 return (SNMP_ERR_NOT_WRITEABLE); 548 } 549 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, 559 ctx->scratch->int1); 560 memcpy(notify->taglist, val->v.octetstring.octets, 561 val->v.octetstring.len); 562 notify->taglist[val->v.octetstring.len] = '\0'; 563 break; 564 565 case LEAF_snmpNotifyType: 566 /* FALLTHROUGH */ 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); 577 } 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; 586 else 587 notify->type = StorageType_readOnly; 588 break; 589 } 590 return (SNMP_ERR_NOERROR); 591 592 case SNMP_OP_COMMIT: 593 switch (val->var.subs[sub - 1]) { 594 case LEAF_snmpNotifyTag: 595 free(ctx->scratch->ptr1); 596 break; 597 case LEAF_snmpNotifyRowStatus: 598 notify = target_get_notify(&val->var, sub); 599 if (notify == NULL) 600 return (SNMP_ERR_GENERR); 601 if (val->v.integer == RowStatus_destroy) 602 return (target_delete_notify(notify)); 603 else 604 notify->status = RowStatus_active; 605 break; 606 default: 607 break; 608 } 609 return (SNMP_ERR_NOERROR); 610 611 case SNMP_OP_ROLLBACK: 612 if ((notify = target_get_notify(&val->var, sub)) == NULL) 613 return (SNMP_ERR_GENERR); 614 615 switch (val->var.subs[sub - 1]) { 616 case LEAF_snmpNotifyTag: 617 strlcpy(notify->taglist, ctx->scratch->ptr1, 618 ctx->scratch->int1); 619 free(ctx->scratch->ptr1); 620 break; 621 case LEAF_snmpNotifyRowStatus: 622 if (ctx->scratch->int1 == RowStatus_destroy) 623 return (target_delete_notify(notify)); 624 break; 625 default: 626 break; 627 } 628 629 default: 630 abort(); 631 } 632 633 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; 639 break; 640 case LEAF_snmpNotifyStorageType: 641 val->v.integer = notify->type; 642 break; 643 case LEAF_snmpNotifyRowStatus: 644 val->v.integer = notify->status; 645 break; 646 default: 647 abort(); 648 } 649 650 return (SNMP_ERR_NOERROR); 651 } 652 653 static void 654 target_append_index(struct asn_oid *oid, uint sub, const char *name) 655 { 656 uint32_t i; 657 658 oid->len = sub + strlen(name); 659 for (i = 0; i < strlen(name); i++) 660 oid->subs[sub + i] = name[i]; 661 } 662 663 static int 664 target_decode_index(const struct asn_oid *oid, uint sub, char *name) 665 { 666 uint32_t i, len; 667 668 if ((len = oid->len - sub) >= SNMP_ADM_STR32_SIZ) 669 return (-1); 670 671 for (i = 0; i < len; i++) 672 name[i] = oid->subs[sub + i]; 673 name[i] = '\0'; 674 675 return (0); 676 } 677 678 static struct target_address * 679 target_get_address(const struct asn_oid *oid, uint sub) 680 { 681 char aname[SNMP_ADM_STR32_SIZ]; 682 struct target_address *addrs; 683 684 if (target_decode_index(oid, sub, aname) < 0) 685 return (NULL); 686 687 for (addrs = target_first_address(); addrs != NULL; 688 addrs = target_next_address(addrs)) 689 if (strcmp(aname, addrs->name) == 0) 690 return (addrs); 691 692 return (NULL); 693 } 694 695 static struct target_address * 696 target_get_next_address(const struct asn_oid * oid, uint sub) 697 { 698 char aname[SNMP_ADM_STR32_SIZ]; 699 struct target_address *addrs; 700 701 if (oid->len - sub == 0) 702 return (target_first_address()); 703 704 if (target_decode_index(oid, sub, aname) < 0) 705 return (NULL); 706 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)); 711 712 return (NULL); 713 } 714 715 static struct target_param * 716 target_get_param(const struct asn_oid *oid, uint sub) 717 { 718 char pname[SNMP_ADM_STR32_SIZ]; 719 struct target_param *param; 720 721 if (target_decode_index(oid, sub, pname) < 0) 722 return (NULL); 723 724 for (param = target_first_param(); param != NULL; 725 param = target_next_param(param)) 726 if (strcmp(pname, param->name) == 0) 727 return (param); 728 729 return (NULL); 730 } 731 732 static struct target_param * 733 target_get_next_param(const struct asn_oid *oid, uint sub) 734 { 735 char pname[SNMP_ADM_STR32_SIZ]; 736 struct target_param *param; 737 738 if (oid->len - sub == 0) 739 return (target_first_param()); 740 741 if (target_decode_index(oid, sub, pname) < 0) 742 return (NULL); 743 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)); 748 749 return (NULL); 750 } 751 752 static struct target_notify * 753 target_get_notify(const struct asn_oid *oid, uint sub) 754 { 755 char nname[SNMP_ADM_STR32_SIZ]; 756 struct target_notify *notify; 757 758 if (target_decode_index(oid, sub, nname) < 0) 759 return (NULL); 760 761 for (notify = target_first_notify(); notify != NULL; 762 notify = target_next_notify(notify)) 763 if (strcmp(nname, notify->name) == 0) 764 return (notify); 765 766 return (NULL); 767 } 768 769 static struct target_notify * 770 target_get_next_notify(const struct asn_oid *oid, uint sub) 771 { 772 char nname[SNMP_ADM_STR32_SIZ]; 773 struct target_notify *notify; 774 775 if (oid->len - sub == 0) 776 return (target_first_notify()); 777 778 if (target_decode_index(oid, sub, nname) < 0) 779 return (NULL); 780 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)); 785 786 return (NULL); 787 } 788 789 static int 790 target_init(struct lmodule *mod, int argc __unused, char *argv[] __unused) 791 { 792 target_module = mod; 793 target_lock = random(); 794 795 return (0); 796 } 797 798 799 static int 800 target_fini(void) 801 { 802 target_flush_all(); 803 or_unregister(reg_target); 804 or_unregister(reg_notification); 805 806 return (0); 807 } 808 809 static void 810 target_start(void) 811 { 812 reg_target = or_register(&oid_target, 813 "The MIB module for managing SNMP Management Targets.", 814 target_module); 815 reg_notification = or_register(&oid_notification, 816 "The MIB module for configuring generation of SNMP notifications.", 817 target_module); 818 } 819 820 static void 821 target_dump(void) 822 { 823 /* XXX: dump the module stats & list of mgmt targets */ 824 } 825 826 const char target_comment[] = \ 827 "This module implements SNMP Management Target MIB Module defined in RFC 3413."; 828 829 const struct snmp_module config = { 830 .comment = target_comment, 831 .init = target_init, 832 .fini = target_fini, 833 .start = target_start, 834 .tree = target_ctree, 835 .dump = target_dump, 836 .tree_size = target_CTREE_SIZE, 837 }; 838