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: releng/10.3/contrib/bsnmp/snmp_target/target_snmp.c 245952 2013-01-26 22:08:21Z pfg $ 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: 302216594Ssyrinx break; 303216594Ssyrinx } 304216594Ssyrinx 305216594Ssyrinx default: 306216594Ssyrinx abort(); 307216594Ssyrinx } 308216594Ssyrinx 309216594Ssyrinx switch (val->var.subs[sub - 1]) { 310216594Ssyrinx case LEAF_snmpTargetAddrTDomain: 311216594Ssyrinx return (oid_get(val, &oid_udp_domain)); 312216594Ssyrinx case LEAF_snmpTargetAddrTAddress: 313216594Ssyrinx return (string_get(val, addrs->address, SNMP_UDP_ADDR_SIZ)); 314216594Ssyrinx case LEAF_snmpTargetAddrTimeout: 315216594Ssyrinx val->v.integer = addrs->timeout; 316216594Ssyrinx break; 317216594Ssyrinx case LEAF_snmpTargetAddrRetryCount: 318216594Ssyrinx val->v.integer = addrs->retry; 319216594Ssyrinx break; 320216594Ssyrinx case LEAF_snmpTargetAddrTagList: 321216594Ssyrinx return (string_get(val, addrs->taglist, -1)); 322216594Ssyrinx case LEAF_snmpTargetAddrParams: 323216594Ssyrinx return (string_get(val, addrs->paramname, -1)); 324216594Ssyrinx case LEAF_snmpTargetAddrStorageType: 325216594Ssyrinx val->v.integer = addrs->type; 326216594Ssyrinx break; 327216594Ssyrinx case LEAF_snmpTargetAddrRowStatus: 328216594Ssyrinx val->v.integer = addrs->status; 329216594Ssyrinx break; 330216594Ssyrinx default: 331216594Ssyrinx abort(); 332216594Ssyrinx } 333216594Ssyrinx 334216594Ssyrinx return (SNMP_ERR_NOERROR); 335216594Ssyrinx} 336216594Ssyrinx 337216594Ssyrinxint 338216594Ssyrinxop_snmp_target_params(struct snmp_context *ctx __unused, struct snmp_value *val, 339216594Ssyrinx uint32_t sub, uint32_t iidx __unused, enum snmp_op op) 340216594Ssyrinx{ 341216594Ssyrinx char pname[SNMP_ADM_STR32_SIZ]; 342216594Ssyrinx struct target_param *param; 343216594Ssyrinx 344216594Ssyrinx switch (op) { 345216594Ssyrinx case SNMP_OP_GET: 346216594Ssyrinx if ((param = target_get_param(&val->var, sub)) == NULL) 347216594Ssyrinx return (SNMP_ERR_NOSUCHNAME); 348216594Ssyrinx break; 349216594Ssyrinx 350216594Ssyrinx case SNMP_OP_GETNEXT: 351216594Ssyrinx if ((param = target_get_next_param(&val->var, sub)) == NULL) 352216594Ssyrinx return (SNMP_ERR_NOSUCHNAME); 353216594Ssyrinx target_append_index(&val->var, sub, param->name); 354216594Ssyrinx break; 355216594Ssyrinx 356216594Ssyrinx case SNMP_OP_SET: 357216594Ssyrinx if ((param = target_get_param(&val->var, sub)) == NULL && 358216594Ssyrinx (val->var.subs[sub - 1] != LEAF_snmpTargetParamsRowStatus || 359216594Ssyrinx val->v.integer != RowStatus_createAndWait)) 360216594Ssyrinx return (SNMP_ERR_NOSUCHNAME); 361216594Ssyrinx 362216594Ssyrinx if (param != NULL) { 363216594Ssyrinx if (community != COMM_INITIALIZE && 364216594Ssyrinx param->type == StorageType_readOnly) 365216594Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 366216594Ssyrinx if (param->status == RowStatus_active && 367216594Ssyrinx val->v.integer != RowStatus_destroy) 368216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 369216594Ssyrinx } 370216594Ssyrinx 371216594Ssyrinx switch (val->var.subs[sub - 1]) { 372216594Ssyrinx case LEAF_snmpTargetParamsMPModel: 373216594Ssyrinx if (val->v.integer != SNMP_MPM_SNMP_V1 && 374216594Ssyrinx val->v.integer != SNMP_MPM_SNMP_V2c && 375216594Ssyrinx val->v.integer != SNMP_MPM_SNMP_V3) 376216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 377216594Ssyrinx ctx->scratch->int1 = param->mpmodel; 378216594Ssyrinx param->mpmodel = val->v.integer; 379216594Ssyrinx break; 380216594Ssyrinx 381216594Ssyrinx case LEAF_snmpTargetParamsSecurityModel: 382216594Ssyrinx if (val->v.integer != SNMP_SECMODEL_SNMPv1 && 383216594Ssyrinx val->v.integer != SNMP_SECMODEL_SNMPv2c && 384216594Ssyrinx val->v.integer != SNMP_SECMODEL_USM) 385216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 386216594Ssyrinx ctx->scratch->int1 = param->sec_model; 387216594Ssyrinx param->sec_model = val->v.integer; 388216594Ssyrinx break; 389216594Ssyrinx 390216594Ssyrinx case LEAF_snmpTargetParamsSecurityName: 391216594Ssyrinx if (val->v.octetstring.len >= SNMP_ADM_STR32_SIZ) 392216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 393216594Ssyrinx ctx->scratch->int1 = strlen(param->secname) + 1; 394216594Ssyrinx ctx->scratch->ptr1 = malloc(ctx->scratch->int1); 395216594Ssyrinx if (ctx->scratch->ptr1 == NULL) 396216594Ssyrinx return (SNMP_ERR_GENERR); 397216594Ssyrinx strlcpy(ctx->scratch->ptr1, param->secname, 398216594Ssyrinx ctx->scratch->int1); 399216594Ssyrinx memcpy(param->secname, val->v.octetstring.octets, 400216594Ssyrinx val->v.octetstring.len); 401216594Ssyrinx param->secname[val->v.octetstring.len] = '\0'; 402216594Ssyrinx break; 403216594Ssyrinx 404216594Ssyrinx case LEAF_snmpTargetParamsSecurityLevel: 405216594Ssyrinx if (val->v.integer != SNMP_noAuthNoPriv && 406216594Ssyrinx val->v.integer != SNMP_authNoPriv && 407216594Ssyrinx val->v.integer != SNMP_authPriv) 408216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 409216594Ssyrinx ctx->scratch->int1 = param->sec_level; 410216594Ssyrinx param->sec_level = val->v.integer; 411216594Ssyrinx break; 412216594Ssyrinx 413216594Ssyrinx case LEAF_snmpTargetParamsStorageType: 414216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 415216594Ssyrinx 416216594Ssyrinx case LEAF_snmpTargetParamsRowStatus: 417216594Ssyrinx if (param != NULL) { 418216594Ssyrinx if (val->v.integer != RowStatus_active && 419216594Ssyrinx val->v.integer != RowStatus_destroy) 420216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 421216594Ssyrinx if (val->v.integer == RowStatus_active && 422216594Ssyrinx (param->sec_model == 0 || 423216594Ssyrinx param->sec_level == 0 || 424216594Ssyrinx strlen(param->secname) == 0)) 425216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 426216594Ssyrinx ctx->scratch->int1 = param->status; 427216594Ssyrinx param->status = val->v.integer; 428216594Ssyrinx return (SNMP_ERR_NOERROR); 429216594Ssyrinx } 430216594Ssyrinx if (val->v.integer != RowStatus_createAndWait || 431216594Ssyrinx target_decode_index(&val->var, sub, pname) < 0) 432216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 433216594Ssyrinx if ((param = target_new_param(pname)) == NULL) 434216594Ssyrinx return (SNMP_ERR_GENERR); 435216594Ssyrinx param->status = RowStatus_destroy; 436216594Ssyrinx if (community != COMM_INITIALIZE) 437216594Ssyrinx param->type = StorageType_volatile; 438216594Ssyrinx else 439216594Ssyrinx param->type = StorageType_readOnly; 440216594Ssyrinx break; 441216594Ssyrinx } 442216594Ssyrinx return (SNMP_ERR_NOERROR); 443216594Ssyrinx 444216594Ssyrinx case SNMP_OP_COMMIT: 445216594Ssyrinx switch (val->var.subs[sub - 1]) { 446216594Ssyrinx case LEAF_snmpTargetParamsSecurityName: 447216594Ssyrinx free(ctx->scratch->ptr1); 448216594Ssyrinx break; 449216594Ssyrinx case LEAF_snmpTargetParamsRowStatus: 450216594Ssyrinx if ((param = target_get_param(&val->var, sub)) == NULL) 451216594Ssyrinx return (SNMP_ERR_GENERR); 452216594Ssyrinx if (val->v.integer == RowStatus_destroy) 453216594Ssyrinx return (target_delete_param(param)); 454216594Ssyrinx break; 455216594Ssyrinx default: 456216594Ssyrinx break; 457216594Ssyrinx } 458216594Ssyrinx return (SNMP_ERR_NOERROR); 459216594Ssyrinx 460216594Ssyrinx case SNMP_OP_ROLLBACK: 461216594Ssyrinx if ((param = target_get_param(&val->var, sub)) == NULL && 462216594Ssyrinx (val->var.subs[sub - 1] != LEAF_snmpTargetParamsRowStatus || 463216594Ssyrinx val->v.integer != RowStatus_createAndWait)) 464216594Ssyrinx return (SNMP_ERR_GENERR); 465216594Ssyrinx switch (val->var.subs[sub - 1]) { 466216594Ssyrinx case LEAF_snmpTargetParamsMPModel: 467216594Ssyrinx param->mpmodel = ctx->scratch->int1; 468216594Ssyrinx break; 469216594Ssyrinx case LEAF_snmpTargetParamsSecurityModel: 470216594Ssyrinx param->sec_model = ctx->scratch->int1; 471216594Ssyrinx break; 472216594Ssyrinx case LEAF_snmpTargetParamsSecurityName: 473216594Ssyrinx strlcpy(param->secname, ctx->scratch->ptr1, 474216594Ssyrinx sizeof(param->secname)); 475216594Ssyrinx free(ctx->scratch->ptr1); 476216594Ssyrinx break; 477216594Ssyrinx case LEAF_snmpTargetParamsSecurityLevel: 478216594Ssyrinx param->sec_level = ctx->scratch->int1; 479216594Ssyrinx break; 480216594Ssyrinx case LEAF_snmpTargetParamsRowStatus: 481216594Ssyrinx if (ctx->scratch->int1 == RowStatus_destroy) 482216594Ssyrinx return (target_delete_param(param)); 483216594Ssyrinx break; 484216594Ssyrinx default: 485216594Ssyrinx break; 486216594Ssyrinx } 487216594Ssyrinx 488216594Ssyrinx return (SNMP_ERR_NOERROR); 489216594Ssyrinx 490216594Ssyrinx default: 491216594Ssyrinx abort(); 492216594Ssyrinx } 493216594Ssyrinx 494216594Ssyrinx switch (val->var.subs[sub - 1]) { 495216594Ssyrinx case LEAF_snmpTargetParamsMPModel: 496216594Ssyrinx val->v.integer = param->mpmodel; 497216594Ssyrinx break; 498216594Ssyrinx case LEAF_snmpTargetParamsSecurityModel: 499216594Ssyrinx val->v.integer = param->sec_model; 500216594Ssyrinx break; 501216594Ssyrinx case LEAF_snmpTargetParamsSecurityName: 502216594Ssyrinx return (string_get(val, param->secname, -1)); 503216594Ssyrinx case LEAF_snmpTargetParamsSecurityLevel: 504216594Ssyrinx val->v.integer = param->sec_level; 505216594Ssyrinx break; 506216594Ssyrinx case LEAF_snmpTargetParamsStorageType: 507216594Ssyrinx val->v.integer = param->type; 508216594Ssyrinx break; 509216594Ssyrinx case LEAF_snmpTargetParamsRowStatus: 510216594Ssyrinx val->v.integer = param->status; 511216594Ssyrinx break; 512216594Ssyrinx default: 513216594Ssyrinx abort(); 514216594Ssyrinx } 515216594Ssyrinx 516216594Ssyrinx return (SNMP_ERR_NOERROR); 517216594Ssyrinx} 518216594Ssyrinx 519216594Ssyrinxint 520216594Ssyrinxop_snmp_notify(struct snmp_context *ctx __unused, struct snmp_value *val, 521216594Ssyrinx uint32_t sub, uint32_t iidx __unused, enum snmp_op op) 522216594Ssyrinx{ 523216594Ssyrinx char nname[SNMP_ADM_STR32_SIZ]; 524216594Ssyrinx struct target_notify *notify; 525216594Ssyrinx 526216594Ssyrinx switch (op) { 527216594Ssyrinx case SNMP_OP_GET: 528216594Ssyrinx if ((notify = target_get_notify(&val->var, sub)) == NULL) 529216594Ssyrinx return (SNMP_ERR_NOSUCHNAME); 530216594Ssyrinx break; 531216594Ssyrinx 532216594Ssyrinx case SNMP_OP_GETNEXT: 533216594Ssyrinx if ((notify = target_get_next_notify(&val->var, sub)) == NULL) 534216594Ssyrinx return (SNMP_ERR_NOSUCHNAME); 535216594Ssyrinx target_append_index(&val->var, sub, notify->name); 536216594Ssyrinx break; 537216594Ssyrinx 538216594Ssyrinx case SNMP_OP_SET: 539216594Ssyrinx if ((notify = target_get_notify(&val->var, sub)) == NULL && 540216594Ssyrinx (val->var.subs[sub - 1] != LEAF_snmpNotifyRowStatus || 541216594Ssyrinx val->v.integer != RowStatus_createAndGo)) 542216594Ssyrinx return (SNMP_ERR_NOSUCHNAME); 543216594Ssyrinx 544216594Ssyrinx if (notify != NULL) { 545216594Ssyrinx if (community != COMM_INITIALIZE && 546216594Ssyrinx notify->type == StorageType_readOnly) 547216594Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 548216594Ssyrinx } 549216594Ssyrinx 550216594Ssyrinx switch (val->var.subs[sub - 1]) { 551216594Ssyrinx case LEAF_snmpNotifyTag: 552216594Ssyrinx if (val->v.octetstring.len >= SNMP_TAG_SIZ) 553216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 554216594Ssyrinx ctx->scratch->int1 = strlen(notify->taglist) + 1; 555216594Ssyrinx ctx->scratch->ptr1 = malloc(ctx->scratch->int1); 556216594Ssyrinx if (ctx->scratch->ptr1 == NULL) 557216594Ssyrinx return (SNMP_ERR_GENERR); 558216594Ssyrinx strlcpy(ctx->scratch->ptr1, notify->taglist, 559216594Ssyrinx ctx->scratch->int1); 560216594Ssyrinx memcpy(notify->taglist, val->v.octetstring.octets, 561216594Ssyrinx val->v.octetstring.len); 562216594Ssyrinx notify->taglist[val->v.octetstring.len] = '\0'; 563216594Ssyrinx break; 564216594Ssyrinx 565216594Ssyrinx case LEAF_snmpNotifyType: 566216594Ssyrinx /* FALLTHROUGH */ 567216594Ssyrinx case LEAF_snmpNotifyStorageType: 568216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 569216594Ssyrinx case LEAF_snmpNotifyRowStatus: 570216594Ssyrinx if (notify != NULL) { 571216594Ssyrinx if (val->v.integer != RowStatus_active && 572216594Ssyrinx val->v.integer != RowStatus_destroy) 573216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 574216594Ssyrinx ctx->scratch->int1 = notify->status; 575216594Ssyrinx notify->status = val->v.integer; 576216594Ssyrinx return (SNMP_ERR_NOERROR); 577216594Ssyrinx } 578216594Ssyrinx if (val->v.integer != RowStatus_createAndGo || 579216594Ssyrinx target_decode_index(&val->var, sub, nname) < 0) 580216594Ssyrinx return (SNMP_ERR_INCONS_VALUE); 581216594Ssyrinx if ((notify = target_new_notify(nname)) == NULL) 582216594Ssyrinx return (SNMP_ERR_GENERR); 583216594Ssyrinx notify->status = RowStatus_destroy; 584216594Ssyrinx if (community != COMM_INITIALIZE) 585216594Ssyrinx notify->type = StorageType_volatile; 586216594Ssyrinx else 587216594Ssyrinx notify->type = StorageType_readOnly; 588216594Ssyrinx break; 589216594Ssyrinx } 590216594Ssyrinx return (SNMP_ERR_NOERROR); 591216594Ssyrinx 592216594Ssyrinx case SNMP_OP_COMMIT: 593216594Ssyrinx switch (val->var.subs[sub - 1]) { 594216594Ssyrinx case LEAF_snmpNotifyTag: 595216594Ssyrinx free(ctx->scratch->ptr1); 596216594Ssyrinx break; 597216594Ssyrinx case LEAF_snmpNotifyRowStatus: 598216594Ssyrinx notify = target_get_notify(&val->var, sub); 599216594Ssyrinx if (notify == NULL) 600216594Ssyrinx return (SNMP_ERR_GENERR); 601216594Ssyrinx if (val->v.integer == RowStatus_destroy) 602216594Ssyrinx return (target_delete_notify(notify)); 603216594Ssyrinx else 604216594Ssyrinx notify->status = RowStatus_active; 605216594Ssyrinx break; 606216594Ssyrinx default: 607216594Ssyrinx break; 608216594Ssyrinx } 609216594Ssyrinx return (SNMP_ERR_NOERROR); 610216594Ssyrinx 611216594Ssyrinx case SNMP_OP_ROLLBACK: 612216594Ssyrinx if ((notify = target_get_notify(&val->var, sub)) == NULL) 613216594Ssyrinx return (SNMP_ERR_GENERR); 614216594Ssyrinx 615216594Ssyrinx switch (val->var.subs[sub - 1]) { 616216594Ssyrinx case LEAF_snmpNotifyTag: 617216594Ssyrinx strlcpy(notify->taglist, ctx->scratch->ptr1, 618216594Ssyrinx ctx->scratch->int1); 619216594Ssyrinx free(ctx->scratch->ptr1); 620216594Ssyrinx break; 621216594Ssyrinx case LEAF_snmpNotifyRowStatus: 622216594Ssyrinx if (ctx->scratch->int1 == RowStatus_destroy) 623216594Ssyrinx return (target_delete_notify(notify)); 624216594Ssyrinx break; 625216594Ssyrinx default: 626216594Ssyrinx break; 627216594Ssyrinx } 628216594Ssyrinx 629216594Ssyrinx default: 630216594Ssyrinx abort(); 631216594Ssyrinx } 632216594Ssyrinx 633216594Ssyrinx 634216594Ssyrinx switch (val->var.subs[sub - 1]) { 635216594Ssyrinx case LEAF_snmpNotifyTag: 636216594Ssyrinx return (string_get(val, notify->taglist, -1)); 637216594Ssyrinx case LEAF_snmpNotifyType: 638216594Ssyrinx val->v.integer = snmpNotifyType_trap; 639216594Ssyrinx break; 640216594Ssyrinx case LEAF_snmpNotifyStorageType: 641216594Ssyrinx val->v.integer = notify->type; 642216594Ssyrinx break; 643216594Ssyrinx case LEAF_snmpNotifyRowStatus: 644216594Ssyrinx val->v.integer = notify->status; 645216594Ssyrinx break; 646216594Ssyrinx default: 647216594Ssyrinx abort(); 648216594Ssyrinx } 649216594Ssyrinx 650216594Ssyrinx return (SNMP_ERR_NOERROR); 651216594Ssyrinx} 652216594Ssyrinx 653216594Ssyrinxstatic void 654216594Ssyrinxtarget_append_index(struct asn_oid *oid, uint sub, const char *name) 655216594Ssyrinx{ 656216594Ssyrinx uint32_t i; 657216594Ssyrinx 658216594Ssyrinx oid->len = sub + strlen(name); 659216594Ssyrinx for (i = 0; i < strlen(name); i++) 660216594Ssyrinx oid->subs[sub + i] = name[i]; 661216594Ssyrinx} 662216594Ssyrinx 663216594Ssyrinxstatic int 664216594Ssyrinxtarget_decode_index(const struct asn_oid *oid, uint sub, char *name) 665216594Ssyrinx{ 666216594Ssyrinx uint32_t i, len; 667216594Ssyrinx 668216594Ssyrinx if ((len = oid->len - sub) >= SNMP_ADM_STR32_SIZ) 669216594Ssyrinx return (-1); 670216594Ssyrinx 671216594Ssyrinx for (i = 0; i < len; i++) 672216594Ssyrinx name[i] = oid->subs[sub + i]; 673216594Ssyrinx name[i] = '\0'; 674216594Ssyrinx 675216594Ssyrinx return (0); 676216594Ssyrinx} 677216594Ssyrinx 678216594Ssyrinxstatic struct target_address * 679216594Ssyrinxtarget_get_address(const struct asn_oid *oid, uint sub) 680216594Ssyrinx{ 681216594Ssyrinx char aname[SNMP_ADM_STR32_SIZ]; 682216594Ssyrinx struct target_address *addrs; 683216594Ssyrinx 684216594Ssyrinx if (target_decode_index(oid, sub, aname) < 0) 685216594Ssyrinx return (NULL); 686216594Ssyrinx 687216594Ssyrinx for (addrs = target_first_address(); addrs != NULL; 688216594Ssyrinx addrs = target_next_address(addrs)) 689216594Ssyrinx if (strcmp(aname, addrs->name) == 0) 690216594Ssyrinx return (addrs); 691216594Ssyrinx 692216594Ssyrinx return (NULL); 693216594Ssyrinx} 694216594Ssyrinx 695216594Ssyrinxstatic struct target_address * 696216594Ssyrinxtarget_get_next_address(const struct asn_oid * oid, uint sub) 697216594Ssyrinx{ 698216594Ssyrinx char aname[SNMP_ADM_STR32_SIZ]; 699216594Ssyrinx struct target_address *addrs; 700216594Ssyrinx 701216594Ssyrinx if (oid->len - sub == 0) 702216594Ssyrinx return (target_first_address()); 703216594Ssyrinx 704216594Ssyrinx if (target_decode_index(oid, sub, aname) < 0) 705216594Ssyrinx return (NULL); 706216594Ssyrinx 707216594Ssyrinx for (addrs = target_first_address(); addrs != NULL; 708216594Ssyrinx addrs = target_next_address(addrs)) 709216594Ssyrinx if (strcmp(aname, addrs->name) == 0) 710216594Ssyrinx return (target_next_address(addrs)); 711216594Ssyrinx 712216594Ssyrinx return (NULL); 713216594Ssyrinx} 714216594Ssyrinx 715216594Ssyrinxstatic struct target_param * 716216594Ssyrinxtarget_get_param(const struct asn_oid *oid, uint sub) 717216594Ssyrinx{ 718216594Ssyrinx char pname[SNMP_ADM_STR32_SIZ]; 719216594Ssyrinx struct target_param *param; 720216594Ssyrinx 721216594Ssyrinx if (target_decode_index(oid, sub, pname) < 0) 722216594Ssyrinx return (NULL); 723216594Ssyrinx 724216594Ssyrinx for (param = target_first_param(); param != NULL; 725216594Ssyrinx param = target_next_param(param)) 726216594Ssyrinx if (strcmp(pname, param->name) == 0) 727216594Ssyrinx return (param); 728216594Ssyrinx 729216594Ssyrinx return (NULL); 730216594Ssyrinx} 731216594Ssyrinx 732216594Ssyrinxstatic struct target_param * 733216594Ssyrinxtarget_get_next_param(const struct asn_oid *oid, uint sub) 734216594Ssyrinx{ 735216594Ssyrinx char pname[SNMP_ADM_STR32_SIZ]; 736216594Ssyrinx struct target_param *param; 737216594Ssyrinx 738216594Ssyrinx if (oid->len - sub == 0) 739216594Ssyrinx return (target_first_param()); 740216594Ssyrinx 741216594Ssyrinx if (target_decode_index(oid, sub, pname) < 0) 742216594Ssyrinx return (NULL); 743216594Ssyrinx 744216594Ssyrinx for (param = target_first_param(); param != NULL; 745216594Ssyrinx param = target_next_param(param)) 746216594Ssyrinx if (strcmp(pname, param->name) == 0) 747216594Ssyrinx return (target_next_param(param)); 748216594Ssyrinx 749216594Ssyrinx return (NULL); 750216594Ssyrinx} 751216594Ssyrinx 752216594Ssyrinxstatic struct target_notify * 753216594Ssyrinxtarget_get_notify(const struct asn_oid *oid, uint sub) 754216594Ssyrinx{ 755216594Ssyrinx char nname[SNMP_ADM_STR32_SIZ]; 756216594Ssyrinx struct target_notify *notify; 757216594Ssyrinx 758216594Ssyrinx if (target_decode_index(oid, sub, nname) < 0) 759216594Ssyrinx return (NULL); 760216594Ssyrinx 761216594Ssyrinx for (notify = target_first_notify(); notify != NULL; 762216594Ssyrinx notify = target_next_notify(notify)) 763216594Ssyrinx if (strcmp(nname, notify->name) == 0) 764216594Ssyrinx return (notify); 765216594Ssyrinx 766216594Ssyrinx return (NULL); 767216594Ssyrinx} 768216594Ssyrinx 769216594Ssyrinxstatic struct target_notify * 770216594Ssyrinxtarget_get_next_notify(const struct asn_oid *oid, uint sub) 771216594Ssyrinx{ 772216594Ssyrinx char nname[SNMP_ADM_STR32_SIZ]; 773216594Ssyrinx struct target_notify *notify; 774216594Ssyrinx 775216594Ssyrinx if (oid->len - sub == 0) 776216594Ssyrinx return (target_first_notify()); 777216594Ssyrinx 778216594Ssyrinx if (target_decode_index(oid, sub, nname) < 0) 779216594Ssyrinx return (NULL); 780216594Ssyrinx 781216594Ssyrinx for (notify = target_first_notify(); notify != NULL; 782216594Ssyrinx notify = target_next_notify(notify)) 783216594Ssyrinx if (strcmp(nname, notify->name) == 0) 784216594Ssyrinx return (target_next_notify(notify)); 785216594Ssyrinx 786216594Ssyrinx return (NULL); 787216594Ssyrinx} 788216594Ssyrinx 789216594Ssyrinxstatic int 790216594Ssyrinxtarget_init(struct lmodule *mod, int argc __unused, char *argv[] __unused) 791216594Ssyrinx{ 792216594Ssyrinx target_module = mod; 793216594Ssyrinx target_lock = random(); 794216594Ssyrinx 795216594Ssyrinx return (0); 796216594Ssyrinx} 797216594Ssyrinx 798216594Ssyrinx 799216594Ssyrinxstatic int 800216594Ssyrinxtarget_fini(void) 801216594Ssyrinx{ 802216594Ssyrinx target_flush_all(); 803216594Ssyrinx or_unregister(reg_target); 804216594Ssyrinx or_unregister(reg_notification); 805216594Ssyrinx 806216594Ssyrinx return (0); 807216594Ssyrinx} 808216594Ssyrinx 809216594Ssyrinxstatic void 810216594Ssyrinxtarget_start(void) 811216594Ssyrinx{ 812216594Ssyrinx reg_target = or_register(&oid_target, 813216594Ssyrinx "The MIB module for managing SNMP Management Targets.", 814216594Ssyrinx target_module); 815216594Ssyrinx reg_notification = or_register(&oid_notification, 816216594Ssyrinx "The MIB module for configuring generation of SNMP notifications.", 817216594Ssyrinx target_module); 818216594Ssyrinx} 819216594Ssyrinx 820216594Ssyrinxstatic void 821216594Ssyrinxtarget_dump(void) 822216594Ssyrinx{ 823216594Ssyrinx /* XXX: dump the module stats & list of mgmt targets */ 824216594Ssyrinx} 825216594Ssyrinx 826216594Ssyrinxconst char target_comment[] = \ 827216594Ssyrinx"This module implements SNMP Management Target MIB Module defined in RFC 3413."; 828216594Ssyrinx 829216594Ssyrinxconst struct snmp_module config = { 830216594Ssyrinx .comment = target_comment, 831216594Ssyrinx .init = target_init, 832216594Ssyrinx .fini = target_fini, 833216594Ssyrinx .start = target_start, 834216594Ssyrinx .tree = target_ctree, 835216594Ssyrinx .dump = target_dump, 836216594Ssyrinx .tree_size = target_CTREE_SIZE, 837216594Ssyrinx}; 838