1216594Ssyrinx/*- 2216594Ssyrinx * Copyright (c) 2010 The FreeBSD Foundation 3216594Ssyrinx * All rights reserved. 4216594Ssyrinx * 5216594Ssyrinx * This software was developed by Shteryana Sotirova Shopova under 6216594Ssyrinx * sponsorship from the FreeBSD Foundation. 7216594Ssyrinx * 8216594Ssyrinx * Redistribution and use in source and binary forms, with or without 9216594Ssyrinx * modification, are permitted provided that the following conditions 10216594Ssyrinx * are met: 11216594Ssyrinx * 1. Redistributions of source code must retain the above copyright 12216594Ssyrinx * notice, this list of conditions and the following disclaimer. 13216594Ssyrinx * 2. Redistributions in binary form must reproduce the above copyright 14216594Ssyrinx * notice, this list of conditions and the following disclaimer in the 15216594Ssyrinx * documentation and/or other materials provided with the distribution. 16216594Ssyrinx * 17216594Ssyrinx * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18216594Ssyrinx * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19216594Ssyrinx * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20216594Ssyrinx * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21216594Ssyrinx * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22216594Ssyrinx * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23216594Ssyrinx * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24216594Ssyrinx * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25216594Ssyrinx * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26216594Ssyrinx * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27216594Ssyrinx * SUCH DAMAGE. 28216594Ssyrinx * 29216594Ssyrinx * $FreeBSD: stable/10/contrib/bsnmp/snmp_target/target_snmp.c 310671 2016-12-28 06:15:39Z ngie $ 30216594Ssyrinx */ 31216594Ssyrinx#include <sys/queue.h> 32216594Ssyrinx#include <sys/types.h> 33216594Ssyrinx 34216594Ssyrinx#include <errno.h> 35216594Ssyrinx#include <stdarg.h> 36216594Ssyrinx#include <stdlib.h> 37216594Ssyrinx#include <stdio.h> 38216594Ssyrinx#include <stdint.h> 39216594Ssyrinx#include <string.h> 40216594Ssyrinx#include <syslog.h> 41216594Ssyrinx 42216594Ssyrinx#include "asn1.h" 43216594Ssyrinx#include "snmp.h" 44216594Ssyrinx#include "snmpmod.h" 45216594Ssyrinx 46216594Ssyrinx#include "target_tree.h" 47216594Ssyrinx#include "target_oid.h" 48216594Ssyrinx 49216594Ssyrinxstatic struct lmodule *target_module; 50216594Ssyrinx/* For the registration. */ 51216594Ssyrinxstatic const struct asn_oid oid_target = OIDX_snmpTargetMIB; 52216594Ssyrinxstatic const struct asn_oid oid_notification = OIDX_snmpNotificationMIB; 53216594Ssyrinx 54216594Ssyrinxstatic uint reg_target; 55216594Ssyrinxstatic uint reg_notification; 56216594Ssyrinx 57216594Ssyrinxstatic int32_t target_lock; 58216594Ssyrinx 59216594Ssyrinxstatic const struct asn_oid oid_udp_domain = OIDX_snmpUDPDomain; 60216594Ssyrinx 61216594Ssyrinx/* 62216594Ssyrinx * Internal datastructures and forward declarations. 63216594Ssyrinx */ 64216594Ssyrinxstatic void target_append_index(struct asn_oid *, uint, 65216594Ssyrinx const char *); 66216594Ssyrinxstatic int target_decode_index(const struct asn_oid *, uint, 67216594Ssyrinx char *); 68216594Ssyrinxstatic struct target_address *target_get_address(const struct asn_oid *, 69216594Ssyrinx uint); 70216594Ssyrinxstatic struct target_address *target_get_next_address(const struct asn_oid *, 71216594Ssyrinx uint); 72216594Ssyrinxstatic struct target_param *target_get_param(const struct asn_oid *, 73216594Ssyrinx uint); 74216594Ssyrinxstatic struct target_param *target_get_next_param(const struct asn_oid *, 75216594Ssyrinx uint); 76216594Ssyrinxstatic struct target_notify *target_get_notify(const struct asn_oid *, 77216594Ssyrinx uint); 78216594Ssyrinxstatic struct target_notify *target_get_next_notify(const struct asn_oid *, 79216594Ssyrinx uint); 80216594Ssyrinx 81216594Ssyrinxint 82216594Ssyrinxop_snmp_target(struct snmp_context *ctx __unused, struct snmp_value *val, 83216594Ssyrinx uint32_t sub, uint32_t iidx __unused, enum snmp_op op) 84216594Ssyrinx{ 85216594Ssyrinx struct snmpd_target_stats *ctx_stats; 86216594Ssyrinx 87216594Ssyrinx if (val->var.subs[sub - 1] == LEAF_snmpTargetSpinLock) { 88216594Ssyrinx switch (op) { 89216594Ssyrinx case SNMP_OP_GET: 90216594Ssyrinx if (++target_lock == INT32_MAX) 91216594Ssyrinx target_lock = 0; 92216594Ssyrinx val->v.integer = target_lock; 93216594Ssyrinx break; 94216594Ssyrinx case SNMP_OP_GETNEXT: 95216594Ssyrinx abort(); 96216594Ssyrinx case SNMP_OP_SET: 97216594Ssyrinx if (val->v.integer != target_lock) 98216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 99216594Ssyrinx break; 100216594Ssyrinx case SNMP_OP_ROLLBACK: 101216594Ssyrinx /* FALLTHROUGH */ 102216594Ssyrinx case SNMP_OP_COMMIT: 103216594Ssyrinx break; 104216594Ssyrinx } 105216594Ssyrinx return (SNMP_ERR_NOERROR); 106216594Ssyrinx } else if (op == SNMP_OP_SET) 107216594Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 108216594Ssyrinx 109216594Ssyrinx if ((ctx_stats = bsnmpd_get_target_stats()) == NULL) 110216594Ssyrinx return (SNMP_ERR_GENERR); 111216594Ssyrinx 112216594Ssyrinx if (op == SNMP_OP_GET) { 113216594Ssyrinx switch (val->var.subs[sub - 1]) { 114216594Ssyrinx case LEAF_snmpUnavailableContexts: 115216594Ssyrinx val->v.uint32 = ctx_stats->unavail_contexts; 116216594Ssyrinx break; 117216594Ssyrinx case LEAF_snmpUnknownContexts: 118216594Ssyrinx val->v.uint32 = ctx_stats->unknown_contexts; 119216594Ssyrinx break; 120216594Ssyrinx default: 121216594Ssyrinx return (SNMP_ERR_NOSUCHNAME); 122216594Ssyrinx } 123216594Ssyrinx return (SNMP_ERR_NOERROR); 124216594Ssyrinx } 125216594Ssyrinx abort(); 126216594Ssyrinx} 127216594Ssyrinx 128216594Ssyrinxint 129216594Ssyrinxop_snmp_target_addrs(struct snmp_context *ctx __unused, struct snmp_value *val, 130216594Ssyrinx uint32_t sub, uint32_t iidx __unused, enum snmp_op op) 131216594Ssyrinx{ 132216594Ssyrinx char aname[SNMP_ADM_STR32_SIZ]; 133216594Ssyrinx struct target_address *addrs; 134216594Ssyrinx 135216594Ssyrinx switch (op) { 136216594Ssyrinx case SNMP_OP_GET: 137216594Ssyrinx if ((addrs = target_get_address(&val->var, sub)) == NULL) 138216594Ssyrinx return (SNMP_ERR_NOSUCHNAME); 139216594Ssyrinx break; 140216594Ssyrinx 141216594Ssyrinx case SNMP_OP_GETNEXT: 142216594Ssyrinx if ((addrs = target_get_next_address(&val->var, sub)) == NULL) 143216594Ssyrinx return (SNMP_ERR_NOSUCHNAME); 144216594Ssyrinx target_append_index(&val->var, sub, addrs->name); 145216594Ssyrinx break; 146216594Ssyrinx 147216594Ssyrinx case SNMP_OP_SET: 148216594Ssyrinx if ((addrs = target_get_address(&val->var, sub)) == NULL && 149216594Ssyrinx (val->var.subs[sub - 1] != LEAF_snmpTargetAddrRowStatus || 150216594Ssyrinx val->v.integer != RowStatus_createAndWait)) 151216594Ssyrinx return (SNMP_ERR_NOSUCHNAME); 152216594Ssyrinx 153216594Ssyrinx if (addrs != NULL) { 154216594Ssyrinx if (community != COMM_INITIALIZE && 155216594Ssyrinx addrs->type == StorageType_readOnly) 156216594Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 157216594Ssyrinx if (addrs->status == RowStatus_active && 158216594Ssyrinx val->v.integer != RowStatus_destroy) 159216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 160216594Ssyrinx } 161216594Ssyrinx 162216594Ssyrinx switch (val->var.subs[sub - 1]) { 163216594Ssyrinx case LEAF_snmpTargetAddrTDomain: 164216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 165216594Ssyrinx case LEAF_snmpTargetAddrTAddress: 166216594Ssyrinx if (val->v.octetstring.len != SNMP_UDP_ADDR_SIZ) 167216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 168216594Ssyrinx ctx->scratch->ptr1 = malloc(SNMP_UDP_ADDR_SIZ); 169216594Ssyrinx if (ctx->scratch->ptr1 == NULL) 170216594Ssyrinx return (SNMP_ERR_GENERR); 171216594Ssyrinx memcpy(ctx->scratch->ptr1, addrs->address, 172216594Ssyrinx SNMP_UDP_ADDR_SIZ); 173216594Ssyrinx memcpy(addrs->address, val->v.octetstring.octets, 174216594Ssyrinx SNMP_UDP_ADDR_SIZ); 175216594Ssyrinx break; 176216594Ssyrinx 177216594Ssyrinx case LEAF_snmpTargetAddrTagList: 178216594Ssyrinx if (val->v.octetstring.len >= SNMP_TAG_SIZ) 179216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 180216594Ssyrinx ctx->scratch->int1 = strlen(addrs->taglist) + 1; 181216594Ssyrinx ctx->scratch->ptr1 = malloc(ctx->scratch->int1); 182216594Ssyrinx if (ctx->scratch->ptr1 == NULL) 183216594Ssyrinx return (SNMP_ERR_GENERR); 184216594Ssyrinx strlcpy(ctx->scratch->ptr1, addrs->taglist, 185216594Ssyrinx ctx->scratch->int1); 186216594Ssyrinx memcpy(addrs->taglist, val->v.octetstring.octets, 187216594Ssyrinx val->v.octetstring.len); 188216594Ssyrinx addrs->taglist[val->v.octetstring.len] = '\0'; 189216594Ssyrinx break; 190216594Ssyrinx 191216594Ssyrinx case LEAF_snmpTargetAddrParams: 192216594Ssyrinx if (val->v.octetstring.len >= SNMP_ADM_STR32_SIZ) 193216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 194216594Ssyrinx ctx->scratch->int1 = strlen(addrs->paramname) + 1; 195216594Ssyrinx ctx->scratch->ptr1 = malloc(ctx->scratch->int1); 196216594Ssyrinx if (ctx->scratch->ptr1 == NULL) 197216594Ssyrinx return (SNMP_ERR_GENERR); 198216594Ssyrinx strlcpy(ctx->scratch->ptr1, addrs->paramname, 199216594Ssyrinx ctx->scratch->int1); 200216594Ssyrinx memcpy(addrs->paramname, val->v.octetstring.octets, 201216594Ssyrinx val->v.octetstring.len); 202216594Ssyrinx addrs->paramname[val->v.octetstring.len] = '\0'; 203216594Ssyrinx break; 204216594Ssyrinx 205216594Ssyrinx case LEAF_snmpTargetAddrRetryCount: 206216594Ssyrinx ctx->scratch->int1 = addrs->retry; 207216594Ssyrinx addrs->retry = val->v.integer; 208216594Ssyrinx break; 209216594Ssyrinx 210216594Ssyrinx case LEAF_snmpTargetAddrTimeout: 211216594Ssyrinx ctx->scratch->int1 = addrs->timeout; 212216594Ssyrinx addrs->timeout = val->v.integer / 10; 213216594Ssyrinx break; 214216594Ssyrinx 215216594Ssyrinx case LEAF_snmpTargetAddrStorageType: 216216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 217216594Ssyrinx 218216594Ssyrinx case LEAF_snmpTargetAddrRowStatus: 219216594Ssyrinx if (addrs != NULL) { 220216594Ssyrinx if (val->v.integer != RowStatus_active && 221216594Ssyrinx val->v.integer != RowStatus_destroy) 222216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 223216594Ssyrinx if (val->v.integer == RowStatus_active && 224216594Ssyrinx (addrs->address[0] == 0 || 225216594Ssyrinx strlen(addrs->taglist) == 0 || 226216594Ssyrinx strlen(addrs->paramname) == 0)) 227216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 228216594Ssyrinx ctx->scratch->int1 = addrs->status; 229216594Ssyrinx addrs->status = val->v.integer; 230216594Ssyrinx return (SNMP_ERR_NOERROR); 231216594Ssyrinx } 232216594Ssyrinx if (val->v.integer != RowStatus_createAndWait || 233216594Ssyrinx target_decode_index(&val->var, sub, aname) < 0) 234216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 235216594Ssyrinx if ((addrs = target_new_address(aname)) == NULL) 236216594Ssyrinx return (SNMP_ERR_GENERR); 237216594Ssyrinx addrs->status = RowStatus_destroy; 238216594Ssyrinx if (community != COMM_INITIALIZE) 239216594Ssyrinx addrs->type = StorageType_volatile; 240216594Ssyrinx else 241216594Ssyrinx addrs->type = StorageType_readOnly; 242216594Ssyrinx break; 243216594Ssyrinx } 244216594Ssyrinx return (SNMP_ERR_NOERROR); 245216594Ssyrinx 246216594Ssyrinx case SNMP_OP_COMMIT: 247216594Ssyrinx switch (val->var.subs[sub - 1]) { 248216594Ssyrinx case LEAF_snmpTargetAddrTAddress: 249216594Ssyrinx case LEAF_snmpTargetAddrTagList: 250216594Ssyrinx case LEAF_snmpTargetAddrParams: 251216594Ssyrinx free(ctx->scratch->ptr1); 252216594Ssyrinx break; 253216594Ssyrinx case LEAF_snmpTargetAddrRowStatus: 254216594Ssyrinx if ((addrs = target_get_address(&val->var, sub)) == NULL) 255216594Ssyrinx return (SNMP_ERR_GENERR); 256216594Ssyrinx if (val->v.integer == RowStatus_destroy) 257216594Ssyrinx return (target_delete_address(addrs)); 258216594Ssyrinx else if (val->v.integer == RowStatus_active) 259216594Ssyrinx return (target_activate_address(addrs)); 260216594Ssyrinx break; 261216594Ssyrinx default: 262216594Ssyrinx break; 263216594Ssyrinx } 264216594Ssyrinx return (SNMP_ERR_NOERROR); 265216594Ssyrinx 266216594Ssyrinx case SNMP_OP_ROLLBACK: 267216594Ssyrinx if ((addrs = target_get_address(&val->var, sub)) == NULL) 268216594Ssyrinx return (SNMP_ERR_GENERR); 269216594Ssyrinx 270216594Ssyrinx switch (val->var.subs[sub - 1]) { 271216594Ssyrinx case LEAF_snmpTargetAddrTAddress: 272216594Ssyrinx memcpy(addrs->address, ctx->scratch->ptr1, 273216594Ssyrinx SNMP_UDP_ADDR_SIZ); 274216594Ssyrinx free(ctx->scratch->ptr1); 275216594Ssyrinx break; 276216594Ssyrinx 277216594Ssyrinx case LEAF_snmpTargetAddrTagList: 278216594Ssyrinx strlcpy(addrs->taglist, ctx->scratch->ptr1, 279216594Ssyrinx ctx->scratch->int1); 280216594Ssyrinx free(ctx->scratch->ptr1); 281216594Ssyrinx break; 282216594Ssyrinx 283216594Ssyrinx case LEAF_snmpTargetAddrParams: 284216594Ssyrinx strlcpy(addrs->paramname, ctx->scratch->ptr1, 285216594Ssyrinx ctx->scratch->int1); 286216594Ssyrinx free(ctx->scratch->ptr1); 287216594Ssyrinx break; 288216594Ssyrinx 289216594Ssyrinx case LEAF_snmpTargetAddrRetryCount: 290216594Ssyrinx addrs->retry = ctx->scratch->int1; 291216594Ssyrinx break; 292216594Ssyrinx 293216594Ssyrinx case LEAF_snmpTargetAddrTimeout: 294216594Ssyrinx addrs->timeout = ctx->scratch->int1; 295216594Ssyrinx break; 296216594Ssyrinx 297216594Ssyrinx case LEAF_snmpTargetAddrRowStatus: 298216594Ssyrinx if (ctx->scratch->int1 == RowStatus_destroy) 299216594Ssyrinx return (target_delete_address(addrs)); 300216594Ssyrinx break; 301216594Ssyrinx default: 302310671Sngie break; 303216594Ssyrinx } 304301661Sngie return (SNMP_ERR_NOERROR); 305216594Ssyrinx 306216594Ssyrinx default: 307216594Ssyrinx abort(); 308216594Ssyrinx } 309216594Ssyrinx 310216594Ssyrinx switch (val->var.subs[sub - 1]) { 311216594Ssyrinx case LEAF_snmpTargetAddrTDomain: 312216594Ssyrinx return (oid_get(val, &oid_udp_domain)); 313216594Ssyrinx case LEAF_snmpTargetAddrTAddress: 314216594Ssyrinx return (string_get(val, addrs->address, SNMP_UDP_ADDR_SIZ)); 315216594Ssyrinx case LEAF_snmpTargetAddrTimeout: 316216594Ssyrinx val->v.integer = addrs->timeout; 317216594Ssyrinx break; 318216594Ssyrinx case LEAF_snmpTargetAddrRetryCount: 319216594Ssyrinx val->v.integer = addrs->retry; 320216594Ssyrinx break; 321216594Ssyrinx case LEAF_snmpTargetAddrTagList: 322216594Ssyrinx return (string_get(val, addrs->taglist, -1)); 323216594Ssyrinx case LEAF_snmpTargetAddrParams: 324216594Ssyrinx return (string_get(val, addrs->paramname, -1)); 325216594Ssyrinx case LEAF_snmpTargetAddrStorageType: 326216594Ssyrinx val->v.integer = addrs->type; 327216594Ssyrinx break; 328216594Ssyrinx case LEAF_snmpTargetAddrRowStatus: 329216594Ssyrinx val->v.integer = addrs->status; 330216594Ssyrinx break; 331216594Ssyrinx default: 332216594Ssyrinx abort(); 333216594Ssyrinx } 334216594Ssyrinx 335216594Ssyrinx return (SNMP_ERR_NOERROR); 336216594Ssyrinx} 337216594Ssyrinx 338216594Ssyrinxint 339216594Ssyrinxop_snmp_target_params(struct snmp_context *ctx __unused, struct snmp_value *val, 340216594Ssyrinx uint32_t sub, uint32_t iidx __unused, enum snmp_op op) 341216594Ssyrinx{ 342216594Ssyrinx char pname[SNMP_ADM_STR32_SIZ]; 343216594Ssyrinx struct target_param *param; 344216594Ssyrinx 345216594Ssyrinx switch (op) { 346216594Ssyrinx case SNMP_OP_GET: 347216594Ssyrinx if ((param = target_get_param(&val->var, sub)) == NULL) 348216594Ssyrinx return (SNMP_ERR_NOSUCHNAME); 349216594Ssyrinx break; 350216594Ssyrinx 351216594Ssyrinx case SNMP_OP_GETNEXT: 352216594Ssyrinx if ((param = target_get_next_param(&val->var, sub)) == NULL) 353216594Ssyrinx return (SNMP_ERR_NOSUCHNAME); 354216594Ssyrinx target_append_index(&val->var, sub, param->name); 355216594Ssyrinx break; 356216594Ssyrinx 357216594Ssyrinx case SNMP_OP_SET: 358216594Ssyrinx if ((param = target_get_param(&val->var, sub)) == NULL && 359216594Ssyrinx (val->var.subs[sub - 1] != LEAF_snmpTargetParamsRowStatus || 360216594Ssyrinx val->v.integer != RowStatus_createAndWait)) 361216594Ssyrinx return (SNMP_ERR_NOSUCHNAME); 362216594Ssyrinx 363216594Ssyrinx if (param != NULL) { 364216594Ssyrinx if (community != COMM_INITIALIZE && 365216594Ssyrinx param->type == StorageType_readOnly) 366216594Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 367216594Ssyrinx if (param->status == RowStatus_active && 368216594Ssyrinx val->v.integer != RowStatus_destroy) 369216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 370216594Ssyrinx } 371216594Ssyrinx 372216594Ssyrinx switch (val->var.subs[sub - 1]) { 373216594Ssyrinx case LEAF_snmpTargetParamsMPModel: 374216594Ssyrinx if (val->v.integer != SNMP_MPM_SNMP_V1 && 375216594Ssyrinx val->v.integer != SNMP_MPM_SNMP_V2c && 376216594Ssyrinx val->v.integer != SNMP_MPM_SNMP_V3) 377216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 378216594Ssyrinx ctx->scratch->int1 = param->mpmodel; 379216594Ssyrinx param->mpmodel = val->v.integer; 380216594Ssyrinx break; 381216594Ssyrinx 382216594Ssyrinx case LEAF_snmpTargetParamsSecurityModel: 383216594Ssyrinx if (val->v.integer != SNMP_SECMODEL_SNMPv1 && 384216594Ssyrinx val->v.integer != SNMP_SECMODEL_SNMPv2c && 385216594Ssyrinx val->v.integer != SNMP_SECMODEL_USM) 386216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 387216594Ssyrinx ctx->scratch->int1 = param->sec_model; 388216594Ssyrinx param->sec_model = val->v.integer; 389216594Ssyrinx break; 390216594Ssyrinx 391216594Ssyrinx case LEAF_snmpTargetParamsSecurityName: 392216594Ssyrinx if (val->v.octetstring.len >= SNMP_ADM_STR32_SIZ) 393216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 394216594Ssyrinx ctx->scratch->int1 = strlen(param->secname) + 1; 395216594Ssyrinx ctx->scratch->ptr1 = malloc(ctx->scratch->int1); 396216594Ssyrinx if (ctx->scratch->ptr1 == NULL) 397216594Ssyrinx return (SNMP_ERR_GENERR); 398216594Ssyrinx strlcpy(ctx->scratch->ptr1, param->secname, 399216594Ssyrinx ctx->scratch->int1); 400216594Ssyrinx memcpy(param->secname, val->v.octetstring.octets, 401216594Ssyrinx val->v.octetstring.len); 402216594Ssyrinx param->secname[val->v.octetstring.len] = '\0'; 403216594Ssyrinx break; 404216594Ssyrinx 405216594Ssyrinx case LEAF_snmpTargetParamsSecurityLevel: 406216594Ssyrinx if (val->v.integer != SNMP_noAuthNoPriv && 407216594Ssyrinx val->v.integer != SNMP_authNoPriv && 408216594Ssyrinx val->v.integer != SNMP_authPriv) 409216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 410216594Ssyrinx ctx->scratch->int1 = param->sec_level; 411216594Ssyrinx param->sec_level = val->v.integer; 412216594Ssyrinx break; 413216594Ssyrinx 414216594Ssyrinx case LEAF_snmpTargetParamsStorageType: 415216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 416216594Ssyrinx 417216594Ssyrinx case LEAF_snmpTargetParamsRowStatus: 418216594Ssyrinx if (param != NULL) { 419216594Ssyrinx if (val->v.integer != RowStatus_active && 420216594Ssyrinx val->v.integer != RowStatus_destroy) 421216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 422216594Ssyrinx if (val->v.integer == RowStatus_active && 423216594Ssyrinx (param->sec_model == 0 || 424216594Ssyrinx param->sec_level == 0 || 425216594Ssyrinx strlen(param->secname) == 0)) 426216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 427216594Ssyrinx ctx->scratch->int1 = param->status; 428216594Ssyrinx param->status = val->v.integer; 429216594Ssyrinx return (SNMP_ERR_NOERROR); 430216594Ssyrinx } 431216594Ssyrinx if (val->v.integer != RowStatus_createAndWait || 432216594Ssyrinx target_decode_index(&val->var, sub, pname) < 0) 433216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 434216594Ssyrinx if ((param = target_new_param(pname)) == NULL) 435216594Ssyrinx return (SNMP_ERR_GENERR); 436216594Ssyrinx param->status = RowStatus_destroy; 437216594Ssyrinx if (community != COMM_INITIALIZE) 438216594Ssyrinx param->type = StorageType_volatile; 439216594Ssyrinx else 440216594Ssyrinx param->type = StorageType_readOnly; 441216594Ssyrinx break; 442216594Ssyrinx } 443216594Ssyrinx return (SNMP_ERR_NOERROR); 444216594Ssyrinx 445216594Ssyrinx case SNMP_OP_COMMIT: 446216594Ssyrinx switch (val->var.subs[sub - 1]) { 447216594Ssyrinx case LEAF_snmpTargetParamsSecurityName: 448216594Ssyrinx free(ctx->scratch->ptr1); 449216594Ssyrinx break; 450216594Ssyrinx case LEAF_snmpTargetParamsRowStatus: 451216594Ssyrinx if ((param = target_get_param(&val->var, sub)) == NULL) 452216594Ssyrinx return (SNMP_ERR_GENERR); 453216594Ssyrinx if (val->v.integer == RowStatus_destroy) 454216594Ssyrinx return (target_delete_param(param)); 455216594Ssyrinx break; 456216594Ssyrinx default: 457216594Ssyrinx break; 458216594Ssyrinx } 459216594Ssyrinx return (SNMP_ERR_NOERROR); 460216594Ssyrinx 461216594Ssyrinx case SNMP_OP_ROLLBACK: 462216594Ssyrinx if ((param = target_get_param(&val->var, sub)) == NULL && 463216594Ssyrinx (val->var.subs[sub - 1] != LEAF_snmpTargetParamsRowStatus || 464216594Ssyrinx val->v.integer != RowStatus_createAndWait)) 465216594Ssyrinx return (SNMP_ERR_GENERR); 466216594Ssyrinx switch (val->var.subs[sub - 1]) { 467216594Ssyrinx case LEAF_snmpTargetParamsMPModel: 468216594Ssyrinx param->mpmodel = ctx->scratch->int1; 469216594Ssyrinx break; 470216594Ssyrinx case LEAF_snmpTargetParamsSecurityModel: 471216594Ssyrinx param->sec_model = ctx->scratch->int1; 472216594Ssyrinx break; 473216594Ssyrinx case LEAF_snmpTargetParamsSecurityName: 474216594Ssyrinx strlcpy(param->secname, ctx->scratch->ptr1, 475216594Ssyrinx sizeof(param->secname)); 476216594Ssyrinx free(ctx->scratch->ptr1); 477216594Ssyrinx break; 478216594Ssyrinx case LEAF_snmpTargetParamsSecurityLevel: 479216594Ssyrinx param->sec_level = ctx->scratch->int1; 480216594Ssyrinx break; 481216594Ssyrinx case LEAF_snmpTargetParamsRowStatus: 482216594Ssyrinx if (ctx->scratch->int1 == RowStatus_destroy) 483216594Ssyrinx return (target_delete_param(param)); 484216594Ssyrinx break; 485216594Ssyrinx default: 486216594Ssyrinx break; 487216594Ssyrinx } 488216594Ssyrinx 489216594Ssyrinx return (SNMP_ERR_NOERROR); 490216594Ssyrinx 491216594Ssyrinx default: 492216594Ssyrinx abort(); 493216594Ssyrinx } 494216594Ssyrinx 495216594Ssyrinx switch (val->var.subs[sub - 1]) { 496216594Ssyrinx case LEAF_snmpTargetParamsMPModel: 497216594Ssyrinx val->v.integer = param->mpmodel; 498216594Ssyrinx break; 499216594Ssyrinx case LEAF_snmpTargetParamsSecurityModel: 500216594Ssyrinx val->v.integer = param->sec_model; 501216594Ssyrinx break; 502216594Ssyrinx case LEAF_snmpTargetParamsSecurityName: 503216594Ssyrinx return (string_get(val, param->secname, -1)); 504216594Ssyrinx case LEAF_snmpTargetParamsSecurityLevel: 505216594Ssyrinx val->v.integer = param->sec_level; 506216594Ssyrinx break; 507216594Ssyrinx case LEAF_snmpTargetParamsStorageType: 508216594Ssyrinx val->v.integer = param->type; 509216594Ssyrinx break; 510216594Ssyrinx case LEAF_snmpTargetParamsRowStatus: 511216594Ssyrinx val->v.integer = param->status; 512216594Ssyrinx break; 513216594Ssyrinx default: 514216594Ssyrinx abort(); 515216594Ssyrinx } 516216594Ssyrinx 517216594Ssyrinx return (SNMP_ERR_NOERROR); 518216594Ssyrinx} 519216594Ssyrinx 520216594Ssyrinxint 521216594Ssyrinxop_snmp_notify(struct snmp_context *ctx __unused, struct snmp_value *val, 522216594Ssyrinx uint32_t sub, uint32_t iidx __unused, enum snmp_op op) 523216594Ssyrinx{ 524216594Ssyrinx char nname[SNMP_ADM_STR32_SIZ]; 525216594Ssyrinx struct target_notify *notify; 526216594Ssyrinx 527216594Ssyrinx switch (op) { 528216594Ssyrinx case SNMP_OP_GET: 529216594Ssyrinx if ((notify = target_get_notify(&val->var, sub)) == NULL) 530216594Ssyrinx return (SNMP_ERR_NOSUCHNAME); 531216594Ssyrinx break; 532216594Ssyrinx 533216594Ssyrinx case SNMP_OP_GETNEXT: 534216594Ssyrinx if ((notify = target_get_next_notify(&val->var, sub)) == NULL) 535216594Ssyrinx return (SNMP_ERR_NOSUCHNAME); 536216594Ssyrinx target_append_index(&val->var, sub, notify->name); 537216594Ssyrinx break; 538216594Ssyrinx 539216594Ssyrinx case SNMP_OP_SET: 540216594Ssyrinx if ((notify = target_get_notify(&val->var, sub)) == NULL && 541216594Ssyrinx (val->var.subs[sub - 1] != LEAF_snmpNotifyRowStatus || 542216594Ssyrinx val->v.integer != RowStatus_createAndGo)) 543216594Ssyrinx return (SNMP_ERR_NOSUCHNAME); 544216594Ssyrinx 545216594Ssyrinx if (notify != NULL) { 546216594Ssyrinx if (community != COMM_INITIALIZE && 547216594Ssyrinx notify->type == StorageType_readOnly) 548216594Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 549216594Ssyrinx } 550216594Ssyrinx 551216594Ssyrinx switch (val->var.subs[sub - 1]) { 552216594Ssyrinx case LEAF_snmpNotifyTag: 553216594Ssyrinx if (val->v.octetstring.len >= SNMP_TAG_SIZ) 554216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 555216594Ssyrinx ctx->scratch->int1 = strlen(notify->taglist) + 1; 556216594Ssyrinx ctx->scratch->ptr1 = malloc(ctx->scratch->int1); 557216594Ssyrinx if (ctx->scratch->ptr1 == NULL) 558216594Ssyrinx return (SNMP_ERR_GENERR); 559216594Ssyrinx strlcpy(ctx->scratch->ptr1, notify->taglist, 560216594Ssyrinx ctx->scratch->int1); 561216594Ssyrinx memcpy(notify->taglist, val->v.octetstring.octets, 562216594Ssyrinx val->v.octetstring.len); 563216594Ssyrinx notify->taglist[val->v.octetstring.len] = '\0'; 564216594Ssyrinx break; 565216594Ssyrinx 566216594Ssyrinx case LEAF_snmpNotifyType: 567216594Ssyrinx /* FALLTHROUGH */ 568216594Ssyrinx case LEAF_snmpNotifyStorageType: 569216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 570216594Ssyrinx case LEAF_snmpNotifyRowStatus: 571216594Ssyrinx if (notify != NULL) { 572216594Ssyrinx if (val->v.integer != RowStatus_active && 573216594Ssyrinx val->v.integer != RowStatus_destroy) 574216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 575216594Ssyrinx ctx->scratch->int1 = notify->status; 576216594Ssyrinx notify->status = val->v.integer; 577216594Ssyrinx return (SNMP_ERR_NOERROR); 578216594Ssyrinx } 579216594Ssyrinx if (val->v.integer != RowStatus_createAndGo || 580216594Ssyrinx target_decode_index(&val->var, sub, nname) < 0) 581216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 582216594Ssyrinx if ((notify = target_new_notify(nname)) == NULL) 583216594Ssyrinx return (SNMP_ERR_GENERR); 584216594Ssyrinx notify->status = RowStatus_destroy; 585216594Ssyrinx if (community != COMM_INITIALIZE) 586216594Ssyrinx notify->type = StorageType_volatile; 587216594Ssyrinx else 588216594Ssyrinx notify->type = StorageType_readOnly; 589216594Ssyrinx break; 590216594Ssyrinx } 591216594Ssyrinx return (SNMP_ERR_NOERROR); 592216594Ssyrinx 593216594Ssyrinx case SNMP_OP_COMMIT: 594216594Ssyrinx switch (val->var.subs[sub - 1]) { 595216594Ssyrinx case LEAF_snmpNotifyTag: 596216594Ssyrinx free(ctx->scratch->ptr1); 597216594Ssyrinx break; 598216594Ssyrinx case LEAF_snmpNotifyRowStatus: 599216594Ssyrinx notify = target_get_notify(&val->var, sub); 600216594Ssyrinx if (notify == NULL) 601216594Ssyrinx return (SNMP_ERR_GENERR); 602216594Ssyrinx if (val->v.integer == RowStatus_destroy) 603216594Ssyrinx return (target_delete_notify(notify)); 604216594Ssyrinx else 605216594Ssyrinx notify->status = RowStatus_active; 606216594Ssyrinx break; 607216594Ssyrinx default: 608216594Ssyrinx break; 609216594Ssyrinx } 610216594Ssyrinx return (SNMP_ERR_NOERROR); 611216594Ssyrinx 612216594Ssyrinx case SNMP_OP_ROLLBACK: 613216594Ssyrinx if ((notify = target_get_notify(&val->var, sub)) == NULL) 614216594Ssyrinx return (SNMP_ERR_GENERR); 615216594Ssyrinx 616216594Ssyrinx switch (val->var.subs[sub - 1]) { 617216594Ssyrinx case LEAF_snmpNotifyTag: 618216594Ssyrinx strlcpy(notify->taglist, ctx->scratch->ptr1, 619216594Ssyrinx ctx->scratch->int1); 620216594Ssyrinx free(ctx->scratch->ptr1); 621216594Ssyrinx break; 622216594Ssyrinx case LEAF_snmpNotifyRowStatus: 623216594Ssyrinx if (ctx->scratch->int1 == RowStatus_destroy) 624216594Ssyrinx return (target_delete_notify(notify)); 625216594Ssyrinx break; 626216594Ssyrinx default: 627216594Ssyrinx break; 628216594Ssyrinx } 629301661Sngie return (SNMP_ERR_NOERROR); 630216594Ssyrinx 631216594Ssyrinx default: 632216594Ssyrinx abort(); 633216594Ssyrinx } 634216594Ssyrinx 635216594Ssyrinx 636216594Ssyrinx switch (val->var.subs[sub - 1]) { 637216594Ssyrinx case LEAF_snmpNotifyTag: 638216594Ssyrinx return (string_get(val, notify->taglist, -1)); 639216594Ssyrinx case LEAF_snmpNotifyType: 640216594Ssyrinx val->v.integer = snmpNotifyType_trap; 641216594Ssyrinx break; 642216594Ssyrinx case LEAF_snmpNotifyStorageType: 643216594Ssyrinx val->v.integer = notify->type; 644216594Ssyrinx break; 645216594Ssyrinx case LEAF_snmpNotifyRowStatus: 646216594Ssyrinx val->v.integer = notify->status; 647216594Ssyrinx break; 648216594Ssyrinx default: 649216594Ssyrinx abort(); 650216594Ssyrinx } 651216594Ssyrinx 652216594Ssyrinx return (SNMP_ERR_NOERROR); 653216594Ssyrinx} 654216594Ssyrinx 655216594Ssyrinxstatic void 656216594Ssyrinxtarget_append_index(struct asn_oid *oid, uint sub, const char *name) 657216594Ssyrinx{ 658216594Ssyrinx uint32_t i; 659216594Ssyrinx 660216594Ssyrinx oid->len = sub + strlen(name); 661216594Ssyrinx for (i = 0; i < strlen(name); i++) 662216594Ssyrinx oid->subs[sub + i] = name[i]; 663216594Ssyrinx} 664216594Ssyrinx 665216594Ssyrinxstatic int 666216594Ssyrinxtarget_decode_index(const struct asn_oid *oid, uint sub, char *name) 667216594Ssyrinx{ 668301661Sngie uint32_t i; 669216594Ssyrinx 670301661Sngie if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >= 671301661Sngie SNMP_ADM_STR32_SIZ) 672216594Ssyrinx return (-1); 673216594Ssyrinx 674301661Sngie for (i = 0; i < oid->subs[sub]; i++) 675301661Sngie name[i] = oid->subs[sub + i + 1]; 676216594Ssyrinx name[i] = '\0'; 677216594Ssyrinx 678216594Ssyrinx return (0); 679216594Ssyrinx} 680216594Ssyrinx 681216594Ssyrinxstatic struct target_address * 682216594Ssyrinxtarget_get_address(const struct asn_oid *oid, uint sub) 683216594Ssyrinx{ 684216594Ssyrinx char aname[SNMP_ADM_STR32_SIZ]; 685216594Ssyrinx struct target_address *addrs; 686216594Ssyrinx 687216594Ssyrinx if (target_decode_index(oid, sub, aname) < 0) 688216594Ssyrinx return (NULL); 689216594Ssyrinx 690216594Ssyrinx for (addrs = target_first_address(); addrs != NULL; 691216594Ssyrinx addrs = target_next_address(addrs)) 692216594Ssyrinx if (strcmp(aname, addrs->name) == 0) 693216594Ssyrinx return (addrs); 694216594Ssyrinx 695216594Ssyrinx return (NULL); 696216594Ssyrinx} 697216594Ssyrinx 698216594Ssyrinxstatic struct target_address * 699216594Ssyrinxtarget_get_next_address(const struct asn_oid * oid, uint sub) 700216594Ssyrinx{ 701216594Ssyrinx char aname[SNMP_ADM_STR32_SIZ]; 702216594Ssyrinx struct target_address *addrs; 703216594Ssyrinx 704216594Ssyrinx if (oid->len - sub == 0) 705216594Ssyrinx return (target_first_address()); 706216594Ssyrinx 707216594Ssyrinx if (target_decode_index(oid, sub, aname) < 0) 708216594Ssyrinx return (NULL); 709216594Ssyrinx 710216594Ssyrinx for (addrs = target_first_address(); addrs != NULL; 711216594Ssyrinx addrs = target_next_address(addrs)) 712216594Ssyrinx if (strcmp(aname, addrs->name) == 0) 713216594Ssyrinx return (target_next_address(addrs)); 714216594Ssyrinx 715216594Ssyrinx return (NULL); 716216594Ssyrinx} 717216594Ssyrinx 718216594Ssyrinxstatic struct target_param * 719216594Ssyrinxtarget_get_param(const struct asn_oid *oid, uint sub) 720216594Ssyrinx{ 721216594Ssyrinx char pname[SNMP_ADM_STR32_SIZ]; 722216594Ssyrinx struct target_param *param; 723216594Ssyrinx 724216594Ssyrinx if (target_decode_index(oid, sub, pname) < 0) 725216594Ssyrinx return (NULL); 726216594Ssyrinx 727216594Ssyrinx for (param = target_first_param(); param != NULL; 728216594Ssyrinx param = target_next_param(param)) 729216594Ssyrinx if (strcmp(pname, param->name) == 0) 730216594Ssyrinx return (param); 731216594Ssyrinx 732216594Ssyrinx return (NULL); 733216594Ssyrinx} 734216594Ssyrinx 735216594Ssyrinxstatic struct target_param * 736216594Ssyrinxtarget_get_next_param(const struct asn_oid *oid, uint sub) 737216594Ssyrinx{ 738216594Ssyrinx char pname[SNMP_ADM_STR32_SIZ]; 739216594Ssyrinx struct target_param *param; 740216594Ssyrinx 741216594Ssyrinx if (oid->len - sub == 0) 742216594Ssyrinx return (target_first_param()); 743216594Ssyrinx 744216594Ssyrinx if (target_decode_index(oid, sub, pname) < 0) 745216594Ssyrinx return (NULL); 746216594Ssyrinx 747216594Ssyrinx for (param = target_first_param(); param != NULL; 748216594Ssyrinx param = target_next_param(param)) 749216594Ssyrinx if (strcmp(pname, param->name) == 0) 750216594Ssyrinx return (target_next_param(param)); 751216594Ssyrinx 752216594Ssyrinx return (NULL); 753216594Ssyrinx} 754216594Ssyrinx 755216594Ssyrinxstatic struct target_notify * 756216594Ssyrinxtarget_get_notify(const struct asn_oid *oid, uint sub) 757216594Ssyrinx{ 758216594Ssyrinx char nname[SNMP_ADM_STR32_SIZ]; 759216594Ssyrinx struct target_notify *notify; 760216594Ssyrinx 761216594Ssyrinx if (target_decode_index(oid, sub, nname) < 0) 762216594Ssyrinx return (NULL); 763216594Ssyrinx 764216594Ssyrinx for (notify = target_first_notify(); notify != NULL; 765216594Ssyrinx notify = target_next_notify(notify)) 766216594Ssyrinx if (strcmp(nname, notify->name) == 0) 767216594Ssyrinx return (notify); 768216594Ssyrinx 769216594Ssyrinx return (NULL); 770216594Ssyrinx} 771216594Ssyrinx 772216594Ssyrinxstatic struct target_notify * 773216594Ssyrinxtarget_get_next_notify(const struct asn_oid *oid, uint sub) 774216594Ssyrinx{ 775216594Ssyrinx char nname[SNMP_ADM_STR32_SIZ]; 776216594Ssyrinx struct target_notify *notify; 777216594Ssyrinx 778216594Ssyrinx if (oid->len - sub == 0) 779216594Ssyrinx return (target_first_notify()); 780216594Ssyrinx 781216594Ssyrinx if (target_decode_index(oid, sub, nname) < 0) 782216594Ssyrinx return (NULL); 783216594Ssyrinx 784216594Ssyrinx for (notify = target_first_notify(); notify != NULL; 785216594Ssyrinx notify = target_next_notify(notify)) 786216594Ssyrinx if (strcmp(nname, notify->name) == 0) 787216594Ssyrinx return (target_next_notify(notify)); 788216594Ssyrinx 789216594Ssyrinx return (NULL); 790216594Ssyrinx} 791216594Ssyrinx 792216594Ssyrinxstatic int 793216594Ssyrinxtarget_init(struct lmodule *mod, int argc __unused, char *argv[] __unused) 794216594Ssyrinx{ 795216594Ssyrinx target_module = mod; 796216594Ssyrinx target_lock = random(); 797216594Ssyrinx 798216594Ssyrinx return (0); 799216594Ssyrinx} 800216594Ssyrinx 801216594Ssyrinx 802216594Ssyrinxstatic int 803216594Ssyrinxtarget_fini(void) 804216594Ssyrinx{ 805216594Ssyrinx target_flush_all(); 806216594Ssyrinx or_unregister(reg_target); 807216594Ssyrinx or_unregister(reg_notification); 808216594Ssyrinx 809216594Ssyrinx return (0); 810216594Ssyrinx} 811216594Ssyrinx 812216594Ssyrinxstatic void 813216594Ssyrinxtarget_start(void) 814216594Ssyrinx{ 815216594Ssyrinx reg_target = or_register(&oid_target, 816216594Ssyrinx "The MIB module for managing SNMP Management Targets.", 817216594Ssyrinx target_module); 818216594Ssyrinx reg_notification = or_register(&oid_notification, 819216594Ssyrinx "The MIB module for configuring generation of SNMP notifications.", 820216594Ssyrinx target_module); 821216594Ssyrinx} 822216594Ssyrinx 823216594Ssyrinxstatic void 824216594Ssyrinxtarget_dump(void) 825216594Ssyrinx{ 826216594Ssyrinx /* XXX: dump the module stats & list of mgmt targets */ 827216594Ssyrinx} 828216594Ssyrinx 829216594Ssyrinxconst char target_comment[] = \ 830216594Ssyrinx"This module implements SNMP Management Target MIB Module defined in RFC 3413."; 831216594Ssyrinx 832216594Ssyrinxconst struct snmp_module config = { 833216594Ssyrinx .comment = target_comment, 834216594Ssyrinx .init = target_init, 835216594Ssyrinx .fini = target_fini, 836216594Ssyrinx .start = target_start, 837216594Ssyrinx .tree = target_ctree, 838216594Ssyrinx .dump = target_dump, 839216594Ssyrinx .tree_size = target_CTREE_SIZE, 840216594Ssyrinx}; 841