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