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