1*c5fcbd5aSmartijn /* $OpenBSD: agentx.c,v 1.24 2023/10/29 11:10:07 martijn Exp $ */
29dbe2cd1Smartijn /*
39dbe2cd1Smartijn * Copyright (c) 2019 Martijn van Duren <martijn@openbsd.org>
49dbe2cd1Smartijn *
59dbe2cd1Smartijn * Permission to use, copy, modify, and distribute this software for any
69dbe2cd1Smartijn * purpose with or without fee is hereby granted, provided that the above
79dbe2cd1Smartijn * copyright notice and this permission notice appear in all copies.
89dbe2cd1Smartijn *
99dbe2cd1Smartijn * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
109dbe2cd1Smartijn * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
119dbe2cd1Smartijn * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
129dbe2cd1Smartijn * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
139dbe2cd1Smartijn * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
149dbe2cd1Smartijn * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
159dbe2cd1Smartijn * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
169dbe2cd1Smartijn */
1781180db9Smartijn #include <netinet/in.h>
189dbe2cd1Smartijn
199dbe2cd1Smartijn #include <errno.h>
2081180db9Smartijn #include <stdarg.h>
219dbe2cd1Smartijn #include <stdlib.h>
229dbe2cd1Smartijn #include <stdio.h>
239dbe2cd1Smartijn #include <string.h>
249dbe2cd1Smartijn #include <strings.h>
2581180db9Smartijn #include <time.h>
269dbe2cd1Smartijn #include <unistd.h>
279dbe2cd1Smartijn
2881180db9Smartijn #include "agentx_internal.h"
29fb16b9d1Sderaadt #include <agentx.h>
309dbe2cd1Smartijn
317d7f9aadSmartijn /*
327d7f9aadSmartijn * ax: struct agentx
337d7f9aadSmartijn * axs: struct agentx_session
347d7f9aadSmartijn * axc: struct agentx_context
357d7f9aadSmartijn * axr: struct agentx_region
367d7f9aadSmartijn * axi: struct agentx_index
377d7f9aadSmartijn * axo: struct agentx_object
387d7f9aadSmartijn * axg: struct agentx_get
397d7f9aadSmartijn * axv: struct agentx_varbind
407d7f9aadSmartijn * axr: struct agentx_request
417d7f9aadSmartijn * cstate: current state
427d7f9aadSmartijn * dstate: desired state
437d7f9aadSmartijn */
447d7f9aadSmartijn
4581180db9Smartijn enum agentx_index_type {
4681180db9Smartijn AXI_TYPE_NEW,
4781180db9Smartijn AXI_TYPE_ANY,
4881180db9Smartijn AXI_TYPE_VALUE,
4981180db9Smartijn AXI_TYPE_DYNAMIC
5081180db9Smartijn };
519dbe2cd1Smartijn
5281180db9Smartijn #define AGENTX_CONTEXT_CTX(axc) (axc->axc_name_default ? NULL : \
5381180db9Smartijn &(axc->axc_name))
5481180db9Smartijn
5581180db9Smartijn struct agentx_agentcaps {
5681180db9Smartijn struct agentx_context *axa_axc;
5781180db9Smartijn struct ax_oid axa_oid;
5881180db9Smartijn struct ax_ostring axa_descr;
5981180db9Smartijn enum agentx_cstate axa_cstate;
6081180db9Smartijn enum agentx_dstate axa_dstate;
6181180db9Smartijn TAILQ_ENTRY(agentx_agentcaps) axa_axc_agentcaps;
6281180db9Smartijn };
6381180db9Smartijn
6481180db9Smartijn struct agentx_region {
6581180db9Smartijn struct agentx_context *axr_axc;
6681180db9Smartijn struct ax_oid axr_oid;
6781180db9Smartijn uint8_t axr_timeout;
6881180db9Smartijn uint8_t axr_priority;
6981180db9Smartijn enum agentx_cstate axr_cstate;
7081180db9Smartijn enum agentx_dstate axr_dstate;
7181180db9Smartijn TAILQ_HEAD(, agentx_index) axr_indices;
7281180db9Smartijn TAILQ_HEAD(, agentx_object) axr_objects;
7381180db9Smartijn TAILQ_ENTRY(agentx_region) axr_axc_regions;
7481180db9Smartijn };
7581180db9Smartijn
7681180db9Smartijn struct agentx_index {
7781180db9Smartijn struct agentx_region *axi_axr;
7881180db9Smartijn enum agentx_index_type axi_type;
7981180db9Smartijn struct ax_varbind axi_vb;
8081180db9Smartijn struct agentx_object **axi_object;
8181180db9Smartijn size_t axi_objectlen;
8281180db9Smartijn size_t axi_objectsize;
8381180db9Smartijn enum agentx_cstate axi_cstate;
8481180db9Smartijn enum agentx_dstate axi_dstate;
8581180db9Smartijn TAILQ_ENTRY(agentx_index) axi_axr_indices;
8681180db9Smartijn };
8781180db9Smartijn
8881180db9Smartijn struct agentx_object {
8981180db9Smartijn struct agentx_region *axo_axr;
9081180db9Smartijn struct ax_oid axo_oid;
9181180db9Smartijn struct agentx_index *axo_index[AGENTX_OID_INDEX_MAX_LEN];
9281180db9Smartijn size_t axo_indexlen;
9381180db9Smartijn int axo_implied;
9481180db9Smartijn uint8_t axo_timeout;
9581180db9Smartijn /* Prevent freeing object while in use by get and set requesets */
9681180db9Smartijn uint32_t axo_lock;
9781180db9Smartijn void (*axo_get)(struct agentx_varbind *);
9881180db9Smartijn enum agentx_cstate axo_cstate;
9981180db9Smartijn enum agentx_dstate axo_dstate;
10081180db9Smartijn RB_ENTRY(agentx_object) axo_axc_objects;
10181180db9Smartijn TAILQ_ENTRY(agentx_object) axo_axr_objects;
10281180db9Smartijn };
10381180db9Smartijn
10481180db9Smartijn struct agentx_varbind {
10581180db9Smartijn struct agentx_get *axv_axg;
10681180db9Smartijn struct agentx_object *axv_axo;
10781180db9Smartijn struct agentx_varbind_index {
10881180db9Smartijn struct agentx_index *axv_axi;
10981180db9Smartijn union ax_data axv_idata;
11081180db9Smartijn } axv_index[AGENTX_OID_INDEX_MAX_LEN];
11181180db9Smartijn size_t axv_indexlen;
11281180db9Smartijn int axv_initialized;
11381180db9Smartijn int axv_include;
11481180db9Smartijn struct ax_varbind axv_vb;
11581180db9Smartijn struct ax_oid axv_start;
11681180db9Smartijn struct ax_oid axv_end;
11781180db9Smartijn enum ax_pdu_error axv_error;
11881180db9Smartijn };
11981180db9Smartijn
12081180db9Smartijn #define AGENTX_GET_CTX(axg) (axg->axg_context_default ? NULL : \
12181180db9Smartijn &(axg->axg_context))
12281180db9Smartijn struct agentx_request {
12381180db9Smartijn uint32_t axr_packetid;
12481180db9Smartijn int (*axr_cb)(struct ax_pdu *, void *);
12581180db9Smartijn void *axr_cookie;
12681180db9Smartijn RB_ENTRY(agentx_request) axr_ax_requests;
12781180db9Smartijn };
12881180db9Smartijn
12981180db9Smartijn static void agentx_start(struct agentx *);
13081180db9Smartijn static void agentx_finalize(struct agentx *, int);
13181180db9Smartijn static void agentx_wantwritenow(struct agentx *, int);
13281180db9Smartijn void (*agentx_wantwrite)(struct agentx *, int) =
13381180db9Smartijn agentx_wantwritenow;
13481180db9Smartijn static void agentx_reset(struct agentx *);
13581180db9Smartijn static void agentx_free_finalize(struct agentx *);
13667d8ab44Smartijn static int agentx_session_retry(struct agentx_session *);
13781180db9Smartijn static int agentx_session_start(struct agentx_session *);
13881180db9Smartijn static int agentx_session_finalize(struct ax_pdu *, void *);
13981180db9Smartijn static int agentx_session_close(struct agentx_session *,
14081180db9Smartijn enum ax_close_reason);
14181180db9Smartijn static int agentx_session_close_finalize(struct ax_pdu *, void *);
14281180db9Smartijn static void agentx_session_free_finalize(struct agentx_session *);
14381180db9Smartijn static void agentx_session_reset(struct agentx_session *);
14467d8ab44Smartijn static int agentx_context_retry(struct agentx_context *);
14581180db9Smartijn static void agentx_context_start(struct agentx_context *);
14681180db9Smartijn static void agentx_context_free_finalize(struct agentx_context *);
14781180db9Smartijn static void agentx_context_reset(struct agentx_context *);
14881180db9Smartijn static int agentx_agentcaps_start(struct agentx_agentcaps *);
14981180db9Smartijn static int agentx_agentcaps_finalize(struct ax_pdu *, void *);
15081180db9Smartijn static int agentx_agentcaps_close(struct agentx_agentcaps *);
15181180db9Smartijn static int agentx_agentcaps_close_finalize(struct ax_pdu *, void *);
15281180db9Smartijn static void agentx_agentcaps_free_finalize(struct agentx_agentcaps *);
15381180db9Smartijn static void agentx_agentcaps_reset(struct agentx_agentcaps *);
15467d8ab44Smartijn static int agentx_region_retry(struct agentx_region *);
15581180db9Smartijn static int agentx_region_start(struct agentx_region *);
15681180db9Smartijn static int agentx_region_finalize(struct ax_pdu *, void *);
15781180db9Smartijn static int agentx_region_close(struct agentx_region *);
15881180db9Smartijn static int agentx_region_close_finalize(struct ax_pdu *, void *);
15981180db9Smartijn static void agentx_region_free_finalize(struct agentx_region *);
16081180db9Smartijn static void agentx_region_reset(struct agentx_region *);
16181180db9Smartijn static struct agentx_index *agentx_index(struct agentx_region *,
16281180db9Smartijn struct ax_varbind *, enum agentx_index_type);
16381180db9Smartijn static int agentx_index_start(struct agentx_index *);
16481180db9Smartijn static int agentx_index_finalize(struct ax_pdu *, void *);
16581180db9Smartijn static void agentx_index_free_finalize(struct agentx_index *);
16681180db9Smartijn static void agentx_index_reset(struct agentx_index *);
16781180db9Smartijn static int agentx_index_close(struct agentx_index *);
16881180db9Smartijn static int agentx_index_close_finalize(struct ax_pdu *, void *);
16981180db9Smartijn static int agentx_object_start(struct agentx_object *);
17081180db9Smartijn static int agentx_object_finalize(struct ax_pdu *, void *);
17181180db9Smartijn static int agentx_object_lock(struct agentx_object *);
17281180db9Smartijn static void agentx_object_unlock(struct agentx_object *);
17381180db9Smartijn static int agentx_object_close(struct agentx_object *);
17481180db9Smartijn static int agentx_object_close_finalize(struct ax_pdu *, void *);
17581180db9Smartijn static void agentx_object_free_finalize(struct agentx_object *);
17681180db9Smartijn static void agentx_object_reset(struct agentx_object *);
17781180db9Smartijn static int agentx_object_cmp(struct agentx_object *,
17881180db9Smartijn struct agentx_object *);
17981180db9Smartijn static void agentx_get_start(struct agentx_context *,
18081180db9Smartijn struct ax_pdu *);
18181180db9Smartijn static void agentx_get_finalize(struct agentx_get *);
18281180db9Smartijn static void agentx_get_free(struct agentx_get *);
18381180db9Smartijn static void agentx_varbind_start(struct agentx_varbind *);
18481180db9Smartijn static void agentx_varbind_finalize(struct agentx_varbind *);
18581180db9Smartijn static void agentx_varbind_nosuchobject(struct agentx_varbind *);
18681180db9Smartijn static void agentx_varbind_nosuchinstance(struct agentx_varbind *);
18781180db9Smartijn static void agentx_varbind_endofmibview(struct agentx_varbind *);
18881180db9Smartijn static void agentx_varbind_error_type(struct agentx_varbind *,
18981180db9Smartijn enum ax_pdu_error, int);
19081180db9Smartijn static int agentx_request(struct agentx *, uint32_t,
19181180db9Smartijn int (*)(struct ax_pdu *, void *), void *);
19281180db9Smartijn static int agentx_request_cmp(struct agentx_request *,
19381180db9Smartijn struct agentx_request *);
19481180db9Smartijn static int agentx_strcat(char **, const char *);
1959c70cf54Smartijn static int agentx_oidfill(struct ax_oid *, const uint32_t[], size_t,
1969c70cf54Smartijn const char **);
19781180db9Smartijn
RB_PROTOTYPE_STATIC(ax_requests,agentx_request,axr_ax_requests,agentx_request_cmp)19881180db9Smartijn RB_PROTOTYPE_STATIC(ax_requests, agentx_request, axr_ax_requests,
19981180db9Smartijn agentx_request_cmp)
20081180db9Smartijn RB_PROTOTYPE_STATIC(axc_objects, agentx_object, axo_axc_objects,
20181180db9Smartijn agentx_object_cmp)
2029dbe2cd1Smartijn
2039dbe2cd1Smartijn struct agentx *
20481180db9Smartijn agentx(void (*nofd)(struct agentx *, void *, int), void *cookie)
2059dbe2cd1Smartijn {
2069dbe2cd1Smartijn struct agentx *ax;
2079dbe2cd1Smartijn
2089dbe2cd1Smartijn if ((ax = calloc(1, sizeof(*ax))) == NULL)
2099dbe2cd1Smartijn return NULL;
21081180db9Smartijn
21181180db9Smartijn ax->ax_nofd = nofd;
21281180db9Smartijn ax->ax_cookie = cookie;
21381180db9Smartijn ax->ax_fd = -1;
21481180db9Smartijn ax->ax_cstate = AX_CSTATE_CLOSE;
21581180db9Smartijn ax->ax_dstate = AX_DSTATE_OPEN;
21681180db9Smartijn TAILQ_INIT(&(ax->ax_sessions));
21781180db9Smartijn TAILQ_INIT(&(ax->ax_getreqs));
21881180db9Smartijn RB_INIT(&(ax->ax_requests));
21981180db9Smartijn
22081180db9Smartijn agentx_start(ax);
2219dbe2cd1Smartijn
2229dbe2cd1Smartijn return ax;
22381180db9Smartijn }
2249dbe2cd1Smartijn
22581180db9Smartijn /*
22681180db9Smartijn * agentx_finalize is not a suitable name for a public API,
22781180db9Smartijn * but use it internally for consistency
22881180db9Smartijn */
22981180db9Smartijn void
agentx_connect(struct agentx * ax,int fd)23081180db9Smartijn agentx_connect(struct agentx *ax, int fd)
23181180db9Smartijn {
23281180db9Smartijn agentx_finalize(ax, fd);
23381180db9Smartijn }
23481180db9Smartijn
23567d8ab44Smartijn void
agentx_retry(struct agentx * ax)23667d8ab44Smartijn agentx_retry(struct agentx *ax)
23767d8ab44Smartijn {
23867d8ab44Smartijn struct agentx_session *axs;
23967d8ab44Smartijn
24067d8ab44Smartijn if (ax->ax_fd == -1)
24167d8ab44Smartijn return;
24267d8ab44Smartijn
24367d8ab44Smartijn TAILQ_FOREACH(axs, &(ax->ax_sessions), axs_ax_sessions) {
24467d8ab44Smartijn if (axs->axs_cstate == AX_CSTATE_OPEN) {
24567d8ab44Smartijn if (agentx_session_retry(axs) == -1)
24667d8ab44Smartijn return;
24767d8ab44Smartijn } else if (axs->axs_cstate == AX_CSTATE_CLOSE) {
24867d8ab44Smartijn if (agentx_session_start(axs) == -1)
24967d8ab44Smartijn return;
25067d8ab44Smartijn }
25167d8ab44Smartijn }
25267d8ab44Smartijn }
25367d8ab44Smartijn
25481180db9Smartijn static void
agentx_start(struct agentx * ax)25581180db9Smartijn agentx_start(struct agentx *ax)
25681180db9Smartijn {
25781180db9Smartijn #ifdef AX_DEBUG
25881180db9Smartijn if (ax->ax_cstate != AX_CSTATE_CLOSE ||
25981180db9Smartijn ax->ax_dstate != AX_DSTATE_OPEN)
26081180db9Smartijn agentx_log_ax_fatalx(ax, "%s: unexpected connect", __func__);
26181180db9Smartijn #endif
26281180db9Smartijn ax->ax_cstate = AX_CSTATE_WAITOPEN;
26381180db9Smartijn ax->ax_nofd(ax, ax->ax_cookie, 0);
26481180db9Smartijn }
26581180db9Smartijn
26681180db9Smartijn static void
agentx_finalize(struct agentx * ax,int fd)26781180db9Smartijn agentx_finalize(struct agentx *ax, int fd)
26881180db9Smartijn {
26981180db9Smartijn struct agentx_session *axs;
27081180db9Smartijn
27181180db9Smartijn if (ax->ax_cstate != AX_CSTATE_WAITOPEN) {
27281180db9Smartijn #ifdef AX_DEBUG
27381180db9Smartijn agentx_log_ax_fatalx(ax, "%s: agentx unexpected connect",
27481180db9Smartijn __func__);
27581180db9Smartijn #else
27681180db9Smartijn agentx_log_ax_warnx(ax,
27781180db9Smartijn "%s: agentx unexpected connect: ignoring", __func__);
27881180db9Smartijn return;
27981180db9Smartijn #endif
28081180db9Smartijn }
28181180db9Smartijn if ((ax->ax_ax = ax_new(fd)) == NULL) {
28281180db9Smartijn agentx_log_ax_warn(ax, "failed to initialize");
28381180db9Smartijn close(fd);
28481180db9Smartijn agentx_reset(ax);
28581180db9Smartijn return;
28681180db9Smartijn }
28781180db9Smartijn
28881180db9Smartijn agentx_log_ax_info(ax, "new connection: %d", fd);
28981180db9Smartijn
29081180db9Smartijn ax->ax_fd = fd;
29181180db9Smartijn ax->ax_cstate = AX_CSTATE_OPEN;
29281180db9Smartijn
29381180db9Smartijn TAILQ_FOREACH(axs, &(ax->ax_sessions), axs_ax_sessions) {
29481180db9Smartijn if (agentx_session_start(axs) == -1)
29581180db9Smartijn break;
29681180db9Smartijn }
29781180db9Smartijn }
29881180db9Smartijn
29981180db9Smartijn static void
agentx_wantwritenow(struct agentx * ax,int fd)30081180db9Smartijn agentx_wantwritenow(struct agentx *ax, int fd)
30181180db9Smartijn {
30281180db9Smartijn agentx_write(ax);
30381180db9Smartijn }
30481180db9Smartijn
30581180db9Smartijn static void
agentx_reset(struct agentx * ax)30681180db9Smartijn agentx_reset(struct agentx *ax)
30781180db9Smartijn {
30833598f3aSmartijn struct agentx_session *axs, *taxs;
30981180db9Smartijn struct agentx_request *axr;
31081180db9Smartijn struct agentx_get *axg;
311f00a771dSmartijn int axfree = ax->ax_free;
31281180db9Smartijn
31381180db9Smartijn ax_free(ax->ax_ax);
31481180db9Smartijn ax->ax_ax = NULL;
31581180db9Smartijn ax->ax_fd = -1;
316f00a771dSmartijn ax->ax_free = 1;
31781180db9Smartijn
31881180db9Smartijn ax->ax_cstate = AX_CSTATE_CLOSE;
31981180db9Smartijn
32081180db9Smartijn while ((axr = RB_MIN(ax_requests, &(ax->ax_requests))) != NULL) {
32181180db9Smartijn RB_REMOVE(ax_requests, &(ax->ax_requests), axr);
32281180db9Smartijn free(axr);
32381180db9Smartijn }
32433598f3aSmartijn TAILQ_FOREACH_SAFE(axs, &(ax->ax_sessions), axs_ax_sessions, taxs)
32581180db9Smartijn agentx_session_reset(axs);
32681180db9Smartijn while (!TAILQ_EMPTY(&(ax->ax_getreqs))) {
32781180db9Smartijn axg = TAILQ_FIRST(&(ax->ax_getreqs));
32881180db9Smartijn axg->axg_axc = NULL;
32981180db9Smartijn TAILQ_REMOVE(&(ax->ax_getreqs), axg, axg_ax_getreqs);
33081180db9Smartijn }
33181180db9Smartijn
332f00a771dSmartijn if (ax->ax_dstate == AX_DSTATE_OPEN)
33381180db9Smartijn agentx_start(ax);
334f00a771dSmartijn
335f00a771dSmartijn if (!axfree)
336f00a771dSmartijn agentx_free_finalize(ax);
3379dbe2cd1Smartijn }
3389dbe2cd1Smartijn
3399dbe2cd1Smartijn void
agentx_free(struct agentx * ax)3409dbe2cd1Smartijn agentx_free(struct agentx *ax)
3419dbe2cd1Smartijn {
34233598f3aSmartijn struct agentx_session *axs, *taxs;
343f00a771dSmartijn int axfree;
34481180db9Smartijn
3459dbe2cd1Smartijn if (ax == NULL)
3469dbe2cd1Smartijn return;
34781180db9Smartijn
348f00a771dSmartijn axfree = ax->ax_free;
349f00a771dSmartijn ax->ax_free = 1;
350f00a771dSmartijn
35181180db9Smartijn /* Malloc throws abort on invalid pointers as well */
352f00a771dSmartijn if (ax->ax_dstate == AX_DSTATE_CLOSE)
35381180db9Smartijn agentx_log_ax_fatalx(ax, "%s: double free", __func__);
35481180db9Smartijn ax->ax_dstate = AX_DSTATE_CLOSE;
35581180db9Smartijn
35633598f3aSmartijn TAILQ_FOREACH_SAFE(axs, &(ax->ax_sessions), axs_ax_sessions, taxs) {
35781180db9Smartijn if (axs->axs_dstate != AX_DSTATE_CLOSE)
35881180db9Smartijn agentx_session_free(axs);
35981180db9Smartijn }
360f00a771dSmartijn if (!axfree)
36181180db9Smartijn agentx_free_finalize(ax);
36281180db9Smartijn }
36381180db9Smartijn
36481180db9Smartijn static void
agentx_free_finalize(struct agentx * ax)36581180db9Smartijn agentx_free_finalize(struct agentx *ax)
36681180db9Smartijn {
367f00a771dSmartijn struct agentx_session *axs, *taxs;
368f00a771dSmartijn
369f00a771dSmartijn ax->ax_free = 0;
370f00a771dSmartijn
371f00a771dSmartijn TAILQ_FOREACH_SAFE(axs, &(ax->ax_sessions), axs_ax_sessions, taxs)
372f00a771dSmartijn agentx_session_free_finalize(axs);
373f00a771dSmartijn
374f00a771dSmartijn if (!TAILQ_EMPTY(&(ax->ax_sessions)) ||
375f00a771dSmartijn !RB_EMPTY(&(ax->ax_requests)) ||
376f00a771dSmartijn ax->ax_dstate != AX_DSTATE_CLOSE)
377f00a771dSmartijn return;
37881180db9Smartijn
37981180db9Smartijn ax_free(ax->ax_ax);
38081180db9Smartijn ax->ax_nofd(ax, ax->ax_cookie, 1);
3819dbe2cd1Smartijn free(ax);
3829dbe2cd1Smartijn }
3839dbe2cd1Smartijn
38481180db9Smartijn struct agentx_session *
agentx_session(struct agentx * ax,uint32_t oid[],size_t oidlen,const char * descr,uint8_t timeout)38581180db9Smartijn agentx_session(struct agentx *ax, uint32_t oid[],
38681180db9Smartijn size_t oidlen, const char *descr, uint8_t timeout)
3879dbe2cd1Smartijn {
38881180db9Smartijn struct agentx_session *axs;
3899c70cf54Smartijn const char *errstr;
3909dbe2cd1Smartijn
39181180db9Smartijn if ((axs = calloc(1, sizeof(*axs))) == NULL)
3929dbe2cd1Smartijn return NULL;
39381180db9Smartijn
39481180db9Smartijn axs->axs_ax = ax;
39581180db9Smartijn axs->axs_timeout = timeout;
3969c70cf54Smartijn /* RFC 2741 section 6.2.1: may send a null Object Identifier */
3979c70cf54Smartijn if (oidlen == 0)
39881180db9Smartijn axs->axs_oid.aoi_idlen = oidlen;
3999c70cf54Smartijn else {
4009c70cf54Smartijn if (agentx_oidfill((&axs->axs_oid), oid, oidlen,
4019c70cf54Smartijn &errstr) == -1) {
4029c70cf54Smartijn #ifdef AX_DEBUG
4039c70cf54Smartijn agentx_log_ax_fatalx(ax, "%s: %s", __func__, errstr);
4049c70cf54Smartijn #else
4059c70cf54Smartijn return NULL;
4069c70cf54Smartijn #endif
4079c70cf54Smartijn }
4089c70cf54Smartijn }
40981180db9Smartijn axs->axs_descr.aos_string = (unsigned char *)strdup(descr);
41081180db9Smartijn if (axs->axs_descr.aos_string == NULL) {
41181180db9Smartijn free(axs);
41281180db9Smartijn return NULL;
41381180db9Smartijn }
41481180db9Smartijn axs->axs_descr.aos_slen = strlen(descr);
41581180db9Smartijn axs->axs_cstate = AX_CSTATE_CLOSE;
41681180db9Smartijn axs->axs_dstate = AX_DSTATE_OPEN;
41781180db9Smartijn TAILQ_INIT(&(axs->axs_contexts));
41881180db9Smartijn TAILQ_INSERT_HEAD(&(ax->ax_sessions), axs, axs_ax_sessions);
41981180db9Smartijn
42081180db9Smartijn if (ax->ax_cstate == AX_CSTATE_OPEN)
42181180db9Smartijn (void) agentx_session_start(axs);
42281180db9Smartijn
42381180db9Smartijn return axs;
4249dbe2cd1Smartijn }
4259dbe2cd1Smartijn
4269dbe2cd1Smartijn static int
agentx_session_retry(struct agentx_session * axs)42767d8ab44Smartijn agentx_session_retry(struct agentx_session *axs)
42867d8ab44Smartijn {
42967d8ab44Smartijn struct agentx_context *axc;
43067d8ab44Smartijn
43167d8ab44Smartijn #ifdef AX_DEBUG
43267d8ab44Smartijn if (axs->axs_cstate != AX_CSTATE_OPEN)
43367d8ab44Smartijn agentx_log_axs_fatalx(axs, "%s: unexpected retry", __func__);
43467d8ab44Smartijn #endif
43567d8ab44Smartijn
43667d8ab44Smartijn TAILQ_FOREACH(axc, &(axs->axs_contexts), axc_axs_contexts) {
43767d8ab44Smartijn if (axc->axc_cstate == AX_CSTATE_OPEN) {
43867d8ab44Smartijn if (agentx_context_retry(axc) == -1)
43967d8ab44Smartijn return -1;
44067d8ab44Smartijn } else if (axc->axc_cstate == AX_CSTATE_CLOSE)
44167d8ab44Smartijn agentx_context_start(axc);
44267d8ab44Smartijn }
44367d8ab44Smartijn return 0;
44467d8ab44Smartijn }
44567d8ab44Smartijn
44667d8ab44Smartijn static int
agentx_session_start(struct agentx_session * axs)44781180db9Smartijn agentx_session_start(struct agentx_session *axs)
4489dbe2cd1Smartijn {
44981180db9Smartijn struct agentx *ax = axs->axs_ax;
45081180db9Smartijn uint32_t packetid;
4519dbe2cd1Smartijn
45281180db9Smartijn #ifdef AX_DEBUG
45381180db9Smartijn if (ax->ax_cstate != AX_CSTATE_OPEN ||
45481180db9Smartijn axs->axs_cstate != AX_CSTATE_CLOSE ||
45581180db9Smartijn axs->axs_dstate != AX_DSTATE_OPEN)
45681180db9Smartijn agentx_log_ax_fatalx(ax, "%s: unexpected session open",
45781180db9Smartijn __func__);
45881180db9Smartijn #endif
45981180db9Smartijn packetid = ax_open(ax->ax_ax, axs->axs_timeout, &(axs->axs_oid),
46081180db9Smartijn &(axs->axs_descr));
46181180db9Smartijn if (packetid == 0) {
46281180db9Smartijn agentx_log_ax_warn(ax, "couldn't generate %s",
46381180db9Smartijn ax_pdutype2string(AX_PDU_TYPE_OPEN));
46481180db9Smartijn agentx_reset(ax);
4659dbe2cd1Smartijn return -1;
4669dbe2cd1Smartijn }
46781180db9Smartijn axs->axs_packetid = packetid;
46881180db9Smartijn agentx_log_ax_info(ax, "opening session");
46981180db9Smartijn axs->axs_cstate = AX_CSTATE_WAITOPEN;
47081180db9Smartijn return agentx_request(ax, packetid, agentx_session_finalize, axs);
4719dbe2cd1Smartijn }
4729dbe2cd1Smartijn
47381180db9Smartijn static int
agentx_session_finalize(struct ax_pdu * pdu,void * cookie)47481180db9Smartijn agentx_session_finalize(struct ax_pdu *pdu, void *cookie)
4759dbe2cd1Smartijn {
47681180db9Smartijn struct agentx_session *axs = cookie;
47781180db9Smartijn struct agentx *ax = axs->axs_ax;
47881180db9Smartijn struct agentx_context *axc;
4799dbe2cd1Smartijn
48081180db9Smartijn #ifdef AX_DEBUG
48181180db9Smartijn if (axs->axs_cstate != AX_CSTATE_WAITOPEN)
48281180db9Smartijn agentx_log_ax_fatalx(ax, "%s: not expecting new session",
48381180db9Smartijn __func__);
4849dbe2cd1Smartijn #endif
4859dbe2cd1Smartijn
48681180db9Smartijn if (pdu->ap_payload.ap_response.ap_error != AX_PDU_ERROR_NOERROR) {
48781180db9Smartijn agentx_log_ax_warnx(ax, "failed to open session: %s",
48881180db9Smartijn ax_error2string(pdu->ap_payload.ap_response.ap_error));
4898fea2aa4Smartijn axs->axs_cstate = AX_CSTATE_CLOSE;
4909dbe2cd1Smartijn return -1;
4919dbe2cd1Smartijn }
4929dbe2cd1Smartijn
49381180db9Smartijn axs->axs_id = pdu->ap_header.aph_sessionid;
49481180db9Smartijn axs->axs_cstate = AX_CSTATE_OPEN;
49581180db9Smartijn
49681180db9Smartijn if (axs->axs_dstate == AX_DSTATE_CLOSE) {
49781180db9Smartijn agentx_session_close(axs, AX_CLOSE_SHUTDOWN);
49881180db9Smartijn return 0;
49981180db9Smartijn }
50081180db9Smartijn
50181180db9Smartijn agentx_log_axs_info(axs, "open");
50281180db9Smartijn
50381180db9Smartijn TAILQ_FOREACH(axc, &(axs->axs_contexts), axc_axs_contexts)
50481180db9Smartijn agentx_context_start(axc);
50581180db9Smartijn return 0;
50681180db9Smartijn }
50781180db9Smartijn
50881180db9Smartijn static int
agentx_session_close(struct agentx_session * axs,enum ax_close_reason reason)50981180db9Smartijn agentx_session_close(struct agentx_session *axs,
51081180db9Smartijn enum ax_close_reason reason)
5119dbe2cd1Smartijn {
51281180db9Smartijn struct agentx *ax = axs->axs_ax;
51381180db9Smartijn uint32_t packetid;
5149dbe2cd1Smartijn
51581180db9Smartijn #ifdef AX_DEBUG
51681180db9Smartijn if (axs->axs_cstate != AX_CSTATE_OPEN)
51781180db9Smartijn agentx_log_ax_fatalx(ax, "%s: unexpected session close",
51881180db9Smartijn __func__);
51981180db9Smartijn #endif
52081180db9Smartijn if ((packetid = ax_close(ax->ax_ax, axs->axs_id, reason)) == 0) {
52181180db9Smartijn agentx_log_axs_warn(axs, "couldn't generate %s",
52281180db9Smartijn ax_pdutype2string(AX_PDU_TYPE_CLOSE));
52381180db9Smartijn agentx_reset(ax);
5249dbe2cd1Smartijn return -1;
52581180db9Smartijn }
5269dbe2cd1Smartijn
52781180db9Smartijn agentx_log_axs_info(axs, "closing session: %s",
52881180db9Smartijn ax_closereason2string(reason));
5299dbe2cd1Smartijn
53081180db9Smartijn axs->axs_cstate = AX_CSTATE_WAITCLOSE;
53181180db9Smartijn return agentx_request(ax, packetid, agentx_session_close_finalize,
53281180db9Smartijn axs);
53381180db9Smartijn }
53481180db9Smartijn
53581180db9Smartijn static int
agentx_session_close_finalize(struct ax_pdu * pdu,void * cookie)53681180db9Smartijn agentx_session_close_finalize(struct ax_pdu *pdu, void *cookie)
53781180db9Smartijn {
53881180db9Smartijn struct agentx_session *axs = cookie;
53981180db9Smartijn struct agentx *ax = axs->axs_ax;
54033598f3aSmartijn struct agentx_context *axc, *taxc;
541f00a771dSmartijn int axfree = ax->ax_free;
54281180db9Smartijn
54381180db9Smartijn #ifdef AX_DEBUG
54481180db9Smartijn if (axs->axs_cstate != AX_CSTATE_WAITCLOSE)
54581180db9Smartijn agentx_log_axs_fatalx(axs, "%s: not expecting session close",
54681180db9Smartijn __func__);
54781180db9Smartijn #endif
54881180db9Smartijn
54981180db9Smartijn if (pdu->ap_payload.ap_response.ap_error != AX_PDU_ERROR_NOERROR) {
55081180db9Smartijn agentx_log_axs_warnx(axs, "failed to close session: %s",
55181180db9Smartijn ax_error2string(pdu->ap_payload.ap_response.ap_error));
55281180db9Smartijn agentx_reset(ax);
5539dbe2cd1Smartijn return -1;
55481180db9Smartijn }
55581180db9Smartijn
55681180db9Smartijn axs->axs_cstate = AX_CSTATE_CLOSE;
557f00a771dSmartijn ax->ax_free = 1;
55881180db9Smartijn
55981180db9Smartijn agentx_log_axs_info(axs, "closed");
56081180db9Smartijn
56133598f3aSmartijn TAILQ_FOREACH_SAFE(axc, &(axs->axs_contexts), axc_axs_contexts, taxc)
56281180db9Smartijn agentx_context_reset(axc);
56381180db9Smartijn
564f00a771dSmartijn if (ax->ax_cstate == AX_CSTATE_OPEN &&
565f00a771dSmartijn axs->axs_dstate == AX_DSTATE_OPEN)
566f00a771dSmartijn agentx_session_start(axs);
567f00a771dSmartijn if (!axfree)
568f00a771dSmartijn agentx_free_finalize(ax);
569f00a771dSmartijn
5709dbe2cd1Smartijn return 0;
5719dbe2cd1Smartijn }
5729dbe2cd1Smartijn
5739dbe2cd1Smartijn void
agentx_session_free(struct agentx_session * axs)57481180db9Smartijn agentx_session_free(struct agentx_session *axs)
5759dbe2cd1Smartijn {
57633598f3aSmartijn struct agentx_context *axc, *taxc;
577f00a771dSmartijn struct agentx *ax;
578f00a771dSmartijn int axfree;
5799dbe2cd1Smartijn
58081180db9Smartijn if (axs == NULL)
58181180db9Smartijn return;
5829dbe2cd1Smartijn
583f00a771dSmartijn ax = axs->axs_ax;
584f00a771dSmartijn axfree = ax->ax_free;
585f00a771dSmartijn ax->ax_free = 1;
586f00a771dSmartijn
58781180db9Smartijn if (axs->axs_dstate == AX_DSTATE_CLOSE)
58881180db9Smartijn agentx_log_axs_fatalx(axs, "%s: double free", __func__);
58981180db9Smartijn
59081180db9Smartijn axs->axs_dstate = AX_DSTATE_CLOSE;
59181180db9Smartijn
59281180db9Smartijn if (axs->axs_cstate == AX_CSTATE_OPEN)
59381180db9Smartijn (void) agentx_session_close(axs, AX_CLOSE_SHUTDOWN);
59481180db9Smartijn
59533598f3aSmartijn TAILQ_FOREACH_SAFE(axc, &(axs->axs_contexts), axc_axs_contexts, taxc) {
59681180db9Smartijn if (axc->axc_dstate != AX_DSTATE_CLOSE)
59781180db9Smartijn agentx_context_free(axc);
5989dbe2cd1Smartijn }
59981180db9Smartijn
600f00a771dSmartijn if (!axfree)
601f00a771dSmartijn agentx_free_finalize(ax);
60281180db9Smartijn }
60381180db9Smartijn
60481180db9Smartijn static void
agentx_session_free_finalize(struct agentx_session * axs)60581180db9Smartijn agentx_session_free_finalize(struct agentx_session *axs)
60681180db9Smartijn {
60781180db9Smartijn struct agentx *ax = axs->axs_ax;
608f00a771dSmartijn struct agentx_context *axc, *taxc;
60981180db9Smartijn
610f00a771dSmartijn TAILQ_FOREACH_SAFE(axc, &(axs->axs_contexts), axc_axs_contexts, taxc)
611f00a771dSmartijn agentx_context_free_finalize(axc);
612f00a771dSmartijn
613f00a771dSmartijn if (!TAILQ_EMPTY(&(axs->axs_contexts)) ||
614f00a771dSmartijn axs->axs_cstate != AX_CSTATE_CLOSE ||
615f00a771dSmartijn axs->axs_dstate != AX_DSTATE_CLOSE)
616f00a771dSmartijn return;
61781180db9Smartijn
61881180db9Smartijn TAILQ_REMOVE(&(ax->ax_sessions), axs, axs_ax_sessions);
61981180db9Smartijn free(axs->axs_descr.aos_string);
62081180db9Smartijn free(axs);
62181180db9Smartijn }
62281180db9Smartijn
62381180db9Smartijn static void
agentx_session_reset(struct agentx_session * axs)62481180db9Smartijn agentx_session_reset(struct agentx_session *axs)
62581180db9Smartijn {
62633598f3aSmartijn struct agentx_context *axc, *taxc;
627f00a771dSmartijn struct agentx *ax = axs->axs_ax;
628f00a771dSmartijn int axfree = ax->ax_free;
629f00a771dSmartijn
630f00a771dSmartijn ax->ax_free = 1;
63181180db9Smartijn
63281180db9Smartijn axs->axs_cstate = AX_CSTATE_CLOSE;
63381180db9Smartijn
63433598f3aSmartijn TAILQ_FOREACH_SAFE(axc, &(axs->axs_contexts), axc_axs_contexts, taxc)
63581180db9Smartijn agentx_context_reset(axc);
63681180db9Smartijn
637f00a771dSmartijn if (!axfree)
638f00a771dSmartijn agentx_free_finalize(ax);
63981180db9Smartijn }
64081180db9Smartijn
64181180db9Smartijn struct agentx_context *
agentx_context(struct agentx_session * axs,const char * name)64281180db9Smartijn agentx_context(struct agentx_session *axs, const char *name)
64381180db9Smartijn {
64481180db9Smartijn struct agentx_context *axc;
64581180db9Smartijn
64681180db9Smartijn if (axs->axs_dstate == AX_DSTATE_CLOSE)
64781180db9Smartijn agentx_log_axs_fatalx(axs, "%s: use after free", __func__);
64881180db9Smartijn
64981180db9Smartijn if ((axc = calloc(1, sizeof(*axc))) == NULL)
65081180db9Smartijn return NULL;
65181180db9Smartijn
65281180db9Smartijn axc->axc_axs = axs;
65381180db9Smartijn axc->axc_name_default = (name == NULL);
65481180db9Smartijn if (name != NULL) {
65581180db9Smartijn axc->axc_name.aos_string = (unsigned char *)strdup(name);
65681180db9Smartijn if (axc->axc_name.aos_string == NULL) {
65781180db9Smartijn free(axc);
65881180db9Smartijn return NULL;
65981180db9Smartijn }
66081180db9Smartijn axc->axc_name.aos_slen = strlen(name);
66181180db9Smartijn }
66281180db9Smartijn axc->axc_cstate = axs->axs_cstate == AX_CSTATE_OPEN ?
66381180db9Smartijn AX_CSTATE_OPEN : AX_CSTATE_CLOSE;
66481180db9Smartijn axc->axc_dstate = AX_DSTATE_OPEN;
66581180db9Smartijn TAILQ_INIT(&(axc->axc_agentcaps));
66681180db9Smartijn TAILQ_INIT(&(axc->axc_regions));
66781180db9Smartijn
66881180db9Smartijn TAILQ_INSERT_HEAD(&(axs->axs_contexts), axc, axc_axs_contexts);
66981180db9Smartijn
67081180db9Smartijn return axc;
67181180db9Smartijn }
67281180db9Smartijn
67367d8ab44Smartijn static int
agentx_context_retry(struct agentx_context * axc)67467d8ab44Smartijn agentx_context_retry(struct agentx_context *axc)
67567d8ab44Smartijn {
67667d8ab44Smartijn struct agentx_agentcaps *axa;
67767d8ab44Smartijn struct agentx_region *axr;
67867d8ab44Smartijn
67967d8ab44Smartijn #ifdef AX_DEBUG
68067d8ab44Smartijn if (axc->axc_cstate != AX_CSTATE_OPEN)
68167d8ab44Smartijn agentx_log_axc_fatalx(axc, "%s: unexpected retry", __func__);
68267d8ab44Smartijn #endif
68367d8ab44Smartijn
68467d8ab44Smartijn TAILQ_FOREACH(axa, &(axc->axc_agentcaps), axa_axc_agentcaps) {
68567d8ab44Smartijn if (axa->axa_cstate == AX_CSTATE_CLOSE) {
68667d8ab44Smartijn if (agentx_agentcaps_start(axa) == -1)
68767d8ab44Smartijn return -1;
68867d8ab44Smartijn }
68967d8ab44Smartijn }
69067d8ab44Smartijn TAILQ_FOREACH(axr, &(axc->axc_regions), axr_axc_regions) {
69167d8ab44Smartijn if (axr->axr_cstate == AX_CSTATE_OPEN) {
69267d8ab44Smartijn if (agentx_region_retry(axr) == -1)
69367d8ab44Smartijn return -1;
69467d8ab44Smartijn } else if (axr->axr_cstate == AX_CSTATE_CLOSE) {
69567d8ab44Smartijn if (agentx_region_start(axr) == -1)
69667d8ab44Smartijn return -1;
69767d8ab44Smartijn }
69867d8ab44Smartijn }
69967d8ab44Smartijn return 0;
70067d8ab44Smartijn }
70167d8ab44Smartijn
70267d8ab44Smartijn
70381180db9Smartijn static void
agentx_context_start(struct agentx_context * axc)70481180db9Smartijn agentx_context_start(struct agentx_context *axc)
70581180db9Smartijn {
70681180db9Smartijn struct agentx_agentcaps *axa;
70781180db9Smartijn struct agentx_region *axr;
70881180db9Smartijn
70981180db9Smartijn #ifdef AX_DEBUG
71081180db9Smartijn if (axc->axc_cstate != AX_CSTATE_CLOSE)
71181180db9Smartijn agentx_log_axc_fatalx(axc, "%s: unexpected context start",
71281180db9Smartijn __func__);
71381180db9Smartijn #endif
71481180db9Smartijn axc->axc_cstate = AX_CSTATE_OPEN;
71581180db9Smartijn
71681180db9Smartijn TAILQ_FOREACH(axa, &(axc->axc_agentcaps), axa_axc_agentcaps) {
71781180db9Smartijn if (agentx_agentcaps_start(axa) == -1)
71881180db9Smartijn return;
71981180db9Smartijn }
72081180db9Smartijn TAILQ_FOREACH(axr, &(axc->axc_regions), axr_axc_regions) {
72181180db9Smartijn if (agentx_region_start(axr) == -1)
72281180db9Smartijn return;
72381180db9Smartijn }
72481180db9Smartijn }
72581180db9Smartijn
72681180db9Smartijn uint32_t
agentx_context_uptime(struct agentx_context * axc)72781180db9Smartijn agentx_context_uptime(struct agentx_context *axc)
72881180db9Smartijn {
72981180db9Smartijn struct timespec cur, res;
73081180db9Smartijn
73181180db9Smartijn if (axc->axc_sysuptimespec.tv_sec == 0 &&
73281180db9Smartijn axc->axc_sysuptimespec.tv_nsec == 0)
73381180db9Smartijn return 0;
73481180db9Smartijn
73581180db9Smartijn (void) clock_gettime(CLOCK_MONOTONIC, &cur);
73681180db9Smartijn
73781180db9Smartijn timespecsub(&cur, &(axc->axc_sysuptimespec), &res);
73881180db9Smartijn
73981180db9Smartijn return axc->axc_sysuptime +
74081180db9Smartijn (uint32_t) ((res.tv_sec * 100) + (res.tv_nsec / 10000000));
74181180db9Smartijn }
74281180db9Smartijn
74381180db9Smartijn struct agentx_object *
agentx_context_object_find(struct agentx_context * axc,const uint32_t oid[],size_t oidlen,int active,int instance)74481180db9Smartijn agentx_context_object_find(struct agentx_context *axc,
74581180db9Smartijn const uint32_t oid[], size_t oidlen, int active, int instance)
74681180db9Smartijn {
74781180db9Smartijn struct agentx_object *axo, axo_search;
7489c70cf54Smartijn const char *errstr;
74981180db9Smartijn
7509c70cf54Smartijn if (agentx_oidfill(&(axo_search.axo_oid), oid, oidlen, &errstr) == -1) {
7519c70cf54Smartijn if (oidlen > AGENTX_OID_MIN_LEN) {
7529c70cf54Smartijn #ifdef AX_DEBUG
7539c70cf54Smartijn agentx_log_axc_fatalx(axc, "%s: %s", __func__, errstr);
7549c70cf54Smartijn #else
7559c70cf54Smartijn agentx_log_axc_warnx(axc, "%s: %s", __func__, errstr);
7569c70cf54Smartijn return NULL;
7579c70cf54Smartijn }
7589c70cf54Smartijn #endif
7599c70cf54Smartijn if (oidlen == 1)
7609c70cf54Smartijn axo_search.axo_oid.aoi_id[0] = oid[0];
76181180db9Smartijn axo_search.axo_oid.aoi_idlen = oidlen;
7629c70cf54Smartijn }
76381180db9Smartijn
76481180db9Smartijn axo = RB_FIND(axc_objects, &(axc->axc_objects), &axo_search);
76581180db9Smartijn while (axo == NULL && !instance && axo_search.axo_oid.aoi_idlen > 0) {
76681180db9Smartijn axo = RB_FIND(axc_objects, &(axc->axc_objects), &axo_search);
76781180db9Smartijn axo_search.axo_oid.aoi_idlen--;
76881180db9Smartijn }
76981180db9Smartijn if (active && axo != NULL && axo->axo_cstate != AX_CSTATE_OPEN)
77081180db9Smartijn return NULL;
77181180db9Smartijn return axo;
77281180db9Smartijn }
77381180db9Smartijn
77481180db9Smartijn struct agentx_object *
77581180db9Smartijn agentx_context_object_nfind(struct agentx_context *axc,
77681180db9Smartijn const uint32_t oid[], size_t oidlen, int active, int inclusive)
77781180db9Smartijn {
77881180db9Smartijn struct agentx_object *axo, axo_search;
7799c70cf54Smartijn const char *errstr;
78081180db9Smartijn
7819c70cf54Smartijn if (agentx_oidfill(&(axo_search.axo_oid), oid, oidlen, &errstr) == -1) {
7829c70cf54Smartijn if (oidlen > AGENTX_OID_MIN_LEN) {
7839c70cf54Smartijn #ifdef AX_DEBUG
7849c70cf54Smartijn agentx_log_axc_fatalx(axc, "%s: %s", __func__, errstr);
7859c70cf54Smartijn #else
7869c70cf54Smartijn agentx_log_axc_warnx(axc, "%s: %s", __func__, errstr);
7879c70cf54Smartijn return NULL;
7889c70cf54Smartijn #endif
7899c70cf54Smartijn }
7909c70cf54Smartijn if (oidlen == 1)
7919c70cf54Smartijn axo_search.axo_oid.aoi_id[0] = oid[0];
79281180db9Smartijn axo_search.axo_oid.aoi_idlen = oidlen;
7939c70cf54Smartijn }
79481180db9Smartijn
79581180db9Smartijn axo = RB_NFIND(axc_objects, &(axc->axc_objects), &axo_search);
79681180db9Smartijn if (!inclusive && axo != NULL &&
797647ce534Smartijn ax_oid_cmp(&(axo->axo_oid), &(axo_search.axo_oid)) <= 0) {
79881180db9Smartijn axo = RB_NEXT(axc_objects, &(axc->axc_objects), axo);
79981180db9Smartijn }
80081180db9Smartijn
80181180db9Smartijn while (active && axo != NULL && axo->axo_cstate != AX_CSTATE_OPEN)
80281180db9Smartijn axo = RB_NEXT(axc_objects, &(axc->axc_objects), axo);
80381180db9Smartijn return axo;
8049dbe2cd1Smartijn }
8059dbe2cd1Smartijn
8069dbe2cd1Smartijn void
80781180db9Smartijn agentx_context_free(struct agentx_context *axc)
8089dbe2cd1Smartijn {
80933598f3aSmartijn struct agentx_agentcaps *axa, *taxa;
81033598f3aSmartijn struct agentx_region *axr, *taxr;
81181180db9Smartijn
81281180db9Smartijn if (axc == NULL)
81381180db9Smartijn return;
81481180db9Smartijn
81581180db9Smartijn #ifdef AX_DEBUG
81681180db9Smartijn if (axc->axc_dstate == AX_DSTATE_CLOSE)
81781180db9Smartijn agentx_log_axc_fatalx(axc, "%s: double free", __func__);
81881180db9Smartijn #endif
81981180db9Smartijn axc->axc_dstate = AX_DSTATE_CLOSE;
82081180db9Smartijn
82181180db9Smartijn TAILQ_FOREACH_SAFE(axa, &(axc->axc_agentcaps), axa_axc_agentcaps,
82233598f3aSmartijn taxa) {
82381180db9Smartijn if (axa->axa_dstate != AX_DSTATE_CLOSE)
82481180db9Smartijn agentx_agentcaps_free(axa);
82581180db9Smartijn }
82633598f3aSmartijn TAILQ_FOREACH_SAFE(axr, &(axc->axc_regions), axr_axc_regions, taxr) {
82781180db9Smartijn if (axr->axr_dstate != AX_DSTATE_CLOSE)
82881180db9Smartijn agentx_region_free(axr);
8299dbe2cd1Smartijn }
8309dbe2cd1Smartijn }
8319dbe2cd1Smartijn
83281180db9Smartijn static void
83381180db9Smartijn agentx_context_free_finalize(struct agentx_context *axc)
8349dbe2cd1Smartijn {
83581180db9Smartijn struct agentx_session *axs = axc->axc_axs;
836f00a771dSmartijn struct agentx_region *axr, *taxr;
837f00a771dSmartijn struct agentx_agentcaps *axa, *taxa;
83881180db9Smartijn
839f00a771dSmartijn TAILQ_FOREACH_SAFE(axa, &(axc->axc_agentcaps), axa_axc_agentcaps, taxa)
840f00a771dSmartijn agentx_agentcaps_free_finalize(axa);
841f00a771dSmartijn TAILQ_FOREACH_SAFE(axr, &(axc->axc_regions), axr_axc_regions, taxr)
842f00a771dSmartijn agentx_region_free_finalize(axr);
843f00a771dSmartijn
84481180db9Smartijn if (!TAILQ_EMPTY(&(axc->axc_regions)) ||
845f00a771dSmartijn !TAILQ_EMPTY(&(axc->axc_agentcaps)) ||
846f00a771dSmartijn axc->axc_cstate != AX_CSTATE_CLOSE ||
847f00a771dSmartijn axc->axc_dstate != AX_DSTATE_CLOSE)
84881180db9Smartijn return;
849f00a771dSmartijn
85081180db9Smartijn TAILQ_REMOVE(&(axs->axs_contexts), axc, axc_axs_contexts);
85181180db9Smartijn free(axc->axc_name.aos_string);
85281180db9Smartijn free(axc);
8539dbe2cd1Smartijn }
8549dbe2cd1Smartijn
85581180db9Smartijn static void
85681180db9Smartijn agentx_context_reset(struct agentx_context *axc)
8579dbe2cd1Smartijn {
85833598f3aSmartijn struct agentx_agentcaps *axa, *taxa;
85933598f3aSmartijn struct agentx_region *axr, *taxr;
860f00a771dSmartijn struct agentx *ax = axc->axc_axs->axs_ax;
861f00a771dSmartijn int axfree = ax->ax_free;
862f00a771dSmartijn
863f00a771dSmartijn ax->ax_free = 1;
86481180db9Smartijn
86581180db9Smartijn axc->axc_cstate = AX_CSTATE_CLOSE;
86681180db9Smartijn axc->axc_sysuptimespec.tv_sec = 0;
86781180db9Smartijn axc->axc_sysuptimespec.tv_nsec = 0;
86881180db9Smartijn
86933598f3aSmartijn TAILQ_FOREACH_SAFE(axa, &(axc->axc_agentcaps), axa_axc_agentcaps, taxa)
87081180db9Smartijn agentx_agentcaps_reset(axa);
87133598f3aSmartijn TAILQ_FOREACH_SAFE(axr, &(axc->axc_regions), axr_axc_regions, taxr)
87281180db9Smartijn agentx_region_reset(axr);
87381180db9Smartijn
874f00a771dSmartijn if (!axfree)
875f00a771dSmartijn agentx_free_finalize(ax);
8769dbe2cd1Smartijn }
8779dbe2cd1Smartijn
87881180db9Smartijn struct agentx_agentcaps *
87981180db9Smartijn agentx_agentcaps(struct agentx_context *axc, uint32_t oid[],
88081180db9Smartijn size_t oidlen, const char *descr)
8819dbe2cd1Smartijn {
88281180db9Smartijn struct agentx_agentcaps *axa;
8839c70cf54Smartijn const char *errstr;
8849dbe2cd1Smartijn
88581180db9Smartijn if (axc->axc_dstate == AX_DSTATE_CLOSE)
88681180db9Smartijn agentx_log_axc_fatalx(axc, "%s: use after free", __func__);
8879dbe2cd1Smartijn
88881180db9Smartijn if ((axa = calloc(1, sizeof(*axa))) == NULL)
88981180db9Smartijn return NULL;
8909dbe2cd1Smartijn
89181180db9Smartijn axa->axa_axc = axc;
8929c70cf54Smartijn if (agentx_oidfill(&(axa->axa_oid), oid, oidlen, &errstr) == -1) {
8939c70cf54Smartijn #ifdef AX_DEBUG
8949c70cf54Smartijn agentx_log_axc_fatalx(axc, "%s: %s", __func__, errstr);
8959c70cf54Smartijn #else
8969c70cf54Smartijn agentx_log_axc_warnx(axc, "%s: %s", __func__, errstr);
8979c70cf54Smartijn return NULL;
8989c70cf54Smartijn #endif
8999c70cf54Smartijn }
90081180db9Smartijn axa->axa_descr.aos_string = (unsigned char *)strdup(descr);
90181180db9Smartijn if (axa->axa_descr.aos_string == NULL) {
90281180db9Smartijn free(axa);
90381180db9Smartijn return NULL;
90481180db9Smartijn }
90581180db9Smartijn axa->axa_descr.aos_slen = strlen(descr);
90681180db9Smartijn axa->axa_cstate = AX_CSTATE_CLOSE;
90781180db9Smartijn axa->axa_dstate = AX_DSTATE_OPEN;
9089dbe2cd1Smartijn
90981180db9Smartijn TAILQ_INSERT_TAIL(&(axc->axc_agentcaps), axa, axa_axc_agentcaps);
9109dbe2cd1Smartijn
91181180db9Smartijn if (axc->axc_cstate == AX_CSTATE_OPEN)
91281180db9Smartijn agentx_agentcaps_start(axa);
9139dbe2cd1Smartijn
91481180db9Smartijn return axa;
9159dbe2cd1Smartijn }
9169dbe2cd1Smartijn
9179dbe2cd1Smartijn static int
91881180db9Smartijn agentx_agentcaps_start(struct agentx_agentcaps *axa)
9199dbe2cd1Smartijn {
92081180db9Smartijn struct agentx_context *axc = axa->axa_axc;
92181180db9Smartijn struct agentx_session *axs = axc->axc_axs;
92281180db9Smartijn struct agentx *ax = axs->axs_ax;
92381180db9Smartijn uint32_t packetid;
92481180db9Smartijn
92581180db9Smartijn #ifdef AX_DEBUG
92681180db9Smartijn if (axc->axc_cstate != AX_CSTATE_OPEN ||
92781180db9Smartijn axa->axa_cstate != AX_CSTATE_CLOSE ||
92881180db9Smartijn axa->axa_dstate != AX_DSTATE_OPEN)
92981180db9Smartijn agentx_log_axc_fatalx(axc,
93081180db9Smartijn "%s: unexpected region registration", __func__);
93181180db9Smartijn #endif
93281180db9Smartijn
93381180db9Smartijn packetid = ax_addagentcaps(ax->ax_ax, axs->axs_id,
93481180db9Smartijn AGENTX_CONTEXT_CTX(axc), &(axa->axa_oid), &(axa->axa_descr));
93581180db9Smartijn if (packetid == 0) {
93681180db9Smartijn agentx_log_axc_warn(axc, "couldn't generate %s",
93781180db9Smartijn ax_pdutype2string(AX_PDU_TYPE_ADDAGENTCAPS));
93881180db9Smartijn agentx_reset(ax);
9399dbe2cd1Smartijn return -1;
9409dbe2cd1Smartijn }
94181180db9Smartijn agentx_log_axc_info(axc, "agentcaps %s: opening",
94281180db9Smartijn ax_oid2string(&(axa->axa_oid)));
94381180db9Smartijn axa->axa_cstate = AX_CSTATE_WAITOPEN;
94481180db9Smartijn return agentx_request(ax, packetid, agentx_agentcaps_finalize,
94581180db9Smartijn axa);
94681180db9Smartijn }
9479dbe2cd1Smartijn
94881180db9Smartijn static int
94981180db9Smartijn agentx_agentcaps_finalize(struct ax_pdu *pdu, void *cookie)
95081180db9Smartijn {
95181180db9Smartijn struct agentx_agentcaps *axa = cookie;
95281180db9Smartijn struct agentx_context *axc = axa->axa_axc;
95381180db9Smartijn
95481180db9Smartijn #ifdef AX_DEBUG
95581180db9Smartijn if (axa->axa_cstate != AX_CSTATE_WAITOPEN)
95681180db9Smartijn agentx_log_axc_fatalx(axc,
95781180db9Smartijn "%s: not expecting agentcaps open", __func__);
95881180db9Smartijn #endif
95981180db9Smartijn
96081180db9Smartijn if (pdu->ap_payload.ap_response.ap_error != AX_PDU_ERROR_NOERROR) {
96181180db9Smartijn /* Agentcaps failing is nothing too serious */
96281180db9Smartijn agentx_log_axc_warn(axc, "agentcaps %s: %s",
96381180db9Smartijn ax_oid2string(&(axa->axa_oid)),
96481180db9Smartijn ax_error2string(pdu->ap_payload.ap_response.ap_error));
96581180db9Smartijn axa->axa_cstate = AX_CSTATE_CLOSE;
96681180db9Smartijn return 0;
9679dbe2cd1Smartijn }
9689dbe2cd1Smartijn
96981180db9Smartijn axa->axa_cstate = AX_CSTATE_OPEN;
97081180db9Smartijn
97181180db9Smartijn agentx_log_axc_info(axc, "agentcaps %s: open",
97281180db9Smartijn ax_oid2string(&(axa->axa_oid)));
97381180db9Smartijn
97481180db9Smartijn if (axa->axa_dstate == AX_DSTATE_CLOSE)
97581180db9Smartijn agentx_agentcaps_close(axa);
97681180db9Smartijn
9779dbe2cd1Smartijn return 0;
9789dbe2cd1Smartijn }
9799dbe2cd1Smartijn
98081180db9Smartijn static int
98181180db9Smartijn agentx_agentcaps_close(struct agentx_agentcaps *axa)
9829dbe2cd1Smartijn {
98381180db9Smartijn struct agentx_context *axc = axa->axa_axc;
98481180db9Smartijn struct agentx_session *axs = axc->axc_axs;
98581180db9Smartijn struct agentx *ax = axs->axs_ax;
98681180db9Smartijn uint32_t packetid;
9879dbe2cd1Smartijn
98881180db9Smartijn #ifdef AX_DEBUG
98981180db9Smartijn if (axa->axa_cstate != AX_CSTATE_OPEN)
99081180db9Smartijn agentx_log_axc_fatalx(axc, "%s: unexpected agentcaps close",
99181180db9Smartijn __func__);
99281180db9Smartijn #endif
99381180db9Smartijn
99481180db9Smartijn axa->axa_cstate = AX_CSTATE_WAITCLOSE;
99581180db9Smartijn if (axs->axs_cstate == AX_CSTATE_WAITCLOSE)
9969dbe2cd1Smartijn return 0;
99781180db9Smartijn
99881180db9Smartijn packetid = ax_removeagentcaps(ax->ax_ax, axs->axs_id,
99981180db9Smartijn AGENTX_CONTEXT_CTX(axc), &(axa->axa_oid));
100081180db9Smartijn if (packetid == 0) {
100181180db9Smartijn agentx_log_axc_warn(axc, "couldn't generate %s",
100281180db9Smartijn ax_pdutype2string(AX_PDU_TYPE_REMOVEAGENTCAPS));
100381180db9Smartijn agentx_reset(ax);
100481180db9Smartijn return -1;
10059dbe2cd1Smartijn }
100681180db9Smartijn agentx_log_axc_info(axc, "agentcaps %s: closing",
100781180db9Smartijn ax_oid2string(&(axa->axa_oid)));
100881180db9Smartijn return agentx_request(ax, packetid,
100981180db9Smartijn agentx_agentcaps_close_finalize, axa);
101081180db9Smartijn }
101181180db9Smartijn
101281180db9Smartijn static int
101381180db9Smartijn agentx_agentcaps_close_finalize(struct ax_pdu *pdu, void *cookie)
101481180db9Smartijn {
101581180db9Smartijn struct agentx_agentcaps *axa = cookie;
101681180db9Smartijn struct agentx_context *axc = axa->axa_axc;
101781180db9Smartijn struct agentx_session *axs = axc->axc_axs;
101881180db9Smartijn struct agentx *ax = axs->axs_ax;
1019f00a771dSmartijn int axfree = ax->ax_free;
102081180db9Smartijn
102181180db9Smartijn #ifdef AX_DEBUG
102281180db9Smartijn if (axa->axa_cstate != AX_CSTATE_WAITCLOSE)
102381180db9Smartijn agentx_log_axc_fatalx(axc, "%s: unexpected agentcaps close",
102481180db9Smartijn __func__);
102581180db9Smartijn #endif
102681180db9Smartijn
102781180db9Smartijn if (pdu->ap_payload.ap_response.ap_error != AX_PDU_ERROR_NOERROR) {
102881180db9Smartijn agentx_log_axc_warnx(axc, "agentcaps %s: %s",
102981180db9Smartijn ax_oid2string(&(axa->axa_oid)),
103081180db9Smartijn ax_error2string(pdu->ap_payload.ap_response.ap_error));
103181180db9Smartijn agentx_reset(ax);
103281180db9Smartijn return -1;
103381180db9Smartijn }
103481180db9Smartijn
103581180db9Smartijn axa->axa_cstate = AX_CSTATE_CLOSE;
1036f00a771dSmartijn ax->ax_free = 1;
103781180db9Smartijn
103881180db9Smartijn agentx_log_axc_info(axc, "agentcaps %s: closed",
103981180db9Smartijn ax_oid2string(&(axa->axa_oid)));
104081180db9Smartijn
1041f00a771dSmartijn if (axc->axc_cstate == AX_CSTATE_OPEN &&
1042f00a771dSmartijn axa->axa_dstate == AX_DSTATE_OPEN)
1043f00a771dSmartijn agentx_agentcaps_start(axa);
1044f00a771dSmartijn
1045f00a771dSmartijn if (!axfree)
1046f00a771dSmartijn agentx_free_finalize(ax);
104781180db9Smartijn return 0;
104881180db9Smartijn }
104981180db9Smartijn
105081180db9Smartijn void
105181180db9Smartijn agentx_agentcaps_free(struct agentx_agentcaps *axa)
105281180db9Smartijn {
1053f00a771dSmartijn struct agentx *ax = axa->axa_axc->axc_axs->axs_ax;
1054f00a771dSmartijn int axfree;
1055f00a771dSmartijn
105681180db9Smartijn if (axa == NULL)
105781180db9Smartijn return;
105881180db9Smartijn
1059f00a771dSmartijn axfree = ax->ax_free;
1060f00a771dSmartijn ax->ax_free = 1;
1061f00a771dSmartijn
106281180db9Smartijn if (axa->axa_dstate == AX_DSTATE_CLOSE)
106381180db9Smartijn agentx_log_axc_fatalx(axa->axa_axc, "%s: double free",
106481180db9Smartijn __func__);
106581180db9Smartijn
106681180db9Smartijn axa->axa_dstate = AX_DSTATE_CLOSE;
106781180db9Smartijn
1068f00a771dSmartijn if (axa->axa_cstate == AX_CSTATE_OPEN)
1069f00a771dSmartijn agentx_agentcaps_close(axa);
107081180db9Smartijn
1071f00a771dSmartijn if (!axfree)
1072f00a771dSmartijn agentx_free_finalize(ax);
107381180db9Smartijn }
107481180db9Smartijn
107581180db9Smartijn static void
107681180db9Smartijn agentx_agentcaps_free_finalize(struct agentx_agentcaps *axa)
107781180db9Smartijn {
107881180db9Smartijn struct agentx_context *axc = axa->axa_axc;
107981180db9Smartijn
108081180db9Smartijn if (axa->axa_dstate != AX_DSTATE_CLOSE ||
108181180db9Smartijn axa->axa_cstate != AX_CSTATE_CLOSE)
1082f00a771dSmartijn return;
108381180db9Smartijn
108481180db9Smartijn TAILQ_REMOVE(&(axc->axc_agentcaps), axa, axa_axc_agentcaps);
108581180db9Smartijn free(axa->axa_descr.aos_string);
108681180db9Smartijn free(axa);
108781180db9Smartijn }
108881180db9Smartijn
108981180db9Smartijn static void
109081180db9Smartijn agentx_agentcaps_reset(struct agentx_agentcaps *axa)
109181180db9Smartijn {
1092f00a771dSmartijn struct agentx *ax = axa->axa_axc->axc_axs->axs_ax;
1093f00a771dSmartijn
109481180db9Smartijn axa->axa_cstate = AX_CSTATE_CLOSE;
109581180db9Smartijn
1096f00a771dSmartijn if (!ax->ax_free)
1097f00a771dSmartijn agentx_free_finalize(ax);
109881180db9Smartijn }
109981180db9Smartijn
110081180db9Smartijn struct agentx_region *
110181180db9Smartijn agentx_region(struct agentx_context *axc, uint32_t oid[],
110281180db9Smartijn size_t oidlen, uint8_t timeout)
110381180db9Smartijn {
110481180db9Smartijn struct agentx_region *axr;
110581180db9Smartijn struct ax_oid tmpoid;
11069c70cf54Smartijn const char *errstr;
110781180db9Smartijn
110881180db9Smartijn if (axc->axc_dstate == AX_DSTATE_CLOSE)
110981180db9Smartijn agentx_log_axc_fatalx(axc, "%s: use after free", __func__);
111081180db9Smartijn
11119c70cf54Smartijn if (agentx_oidfill(&tmpoid, oid, oidlen, &errstr) == -1) {
11129c70cf54Smartijn #ifdef AX_DEBUG
11139c70cf54Smartijn agentx_log_axc_fatalx(axc, "%s: %s", __func__, errstr);
11149c70cf54Smartijn #else
11159c70cf54Smartijn return NULL;
11169c70cf54Smartijn #endif
11179c70cf54Smartijn
11189c70cf54Smartijn }
111981180db9Smartijn TAILQ_FOREACH(axr, &(axc->axc_regions), axr_axc_regions) {
112081180db9Smartijn if (ax_oid_cmp(&(axr->axr_oid), &tmpoid) == 0) {
112181180db9Smartijn #ifdef AX_DEBUG
112281180db9Smartijn agentx_log_axc_fatalx(axc,
112381180db9Smartijn "%s: duplicate region registration", __func__);
112481180db9Smartijn #else
112581180db9Smartijn errno = EINVAL;
112681180db9Smartijn return NULL;
112781180db9Smartijn #endif
112881180db9Smartijn }
112981180db9Smartijn }
113081180db9Smartijn
113181180db9Smartijn if ((axr = calloc(1, sizeof(*axr))) == NULL)
113281180db9Smartijn return NULL;
113381180db9Smartijn
113481180db9Smartijn axr->axr_axc = axc;
113581180db9Smartijn axr->axr_timeout = timeout;
113681180db9Smartijn axr->axr_priority = AX_PRIORITY_DEFAULT;
113781180db9Smartijn bcopy(&tmpoid, &(axr->axr_oid), sizeof(axr->axr_oid));
113881180db9Smartijn axr->axr_cstate = AX_CSTATE_CLOSE;
113981180db9Smartijn axr->axr_dstate = AX_DSTATE_OPEN;
114081180db9Smartijn TAILQ_INIT(&(axr->axr_indices));
114181180db9Smartijn TAILQ_INIT(&(axr->axr_objects));
114281180db9Smartijn
114381180db9Smartijn TAILQ_INSERT_HEAD(&(axc->axc_regions), axr, axr_axc_regions);
114481180db9Smartijn
114581180db9Smartijn if (axc->axc_cstate == AX_CSTATE_OPEN)
114681180db9Smartijn (void) agentx_region_start(axr);
114781180db9Smartijn
114881180db9Smartijn return axr;
114981180db9Smartijn }
115081180db9Smartijn
115181180db9Smartijn static int
115267d8ab44Smartijn agentx_region_retry(struct agentx_region *axr)
115367d8ab44Smartijn {
115467d8ab44Smartijn struct agentx_index *axi;
115567d8ab44Smartijn struct agentx_object *axo;
115667d8ab44Smartijn
115767d8ab44Smartijn #ifdef AX_DEBUG
115867d8ab44Smartijn if (axr->axr_cstate != AX_CSTATE_OPEN)
115967d8ab44Smartijn agentx_log_axc_fatalx(axr->axr_axc,
116067d8ab44Smartijn "%s: unexpected retry", __func__);
116167d8ab44Smartijn #endif
116267d8ab44Smartijn
116367d8ab44Smartijn TAILQ_FOREACH(axi, &(axr->axr_indices), axi_axr_indices) {
116467d8ab44Smartijn if (axi->axi_cstate == AX_CSTATE_CLOSE) {
116567d8ab44Smartijn if (agentx_index_start(axi) == -1)
116667d8ab44Smartijn return -1;
116767d8ab44Smartijn }
116867d8ab44Smartijn }
116967d8ab44Smartijn TAILQ_FOREACH(axo, &(axr->axr_objects), axo_axr_objects) {
117067d8ab44Smartijn if (axo->axo_cstate == AX_CSTATE_CLOSE) {
117167d8ab44Smartijn if (agentx_object_start(axo) == -1)
117267d8ab44Smartijn return -1;
117367d8ab44Smartijn }
117467d8ab44Smartijn }
117567d8ab44Smartijn return 0;
117667d8ab44Smartijn }
117767d8ab44Smartijn
117867d8ab44Smartijn static int
117981180db9Smartijn agentx_region_start(struct agentx_region *axr)
118081180db9Smartijn {
118181180db9Smartijn struct agentx_context *axc = axr->axr_axc;
118281180db9Smartijn struct agentx_session *axs = axc->axc_axs;
118381180db9Smartijn struct agentx *ax = axs->axs_ax;
118481180db9Smartijn uint32_t packetid;
118581180db9Smartijn
118681180db9Smartijn #ifdef AX_DEBUG
118781180db9Smartijn if (axc->axc_cstate != AX_CSTATE_OPEN ||
118881180db9Smartijn axr->axr_cstate != AX_CSTATE_CLOSE ||
118981180db9Smartijn axr->axr_dstate != AX_DSTATE_OPEN)
119081180db9Smartijn agentx_log_axc_fatalx(axc,
119181180db9Smartijn "%s: unexpected region registration", __func__);
119281180db9Smartijn #endif
119381180db9Smartijn
119481180db9Smartijn packetid = ax_register(ax->ax_ax, 0, axs->axs_id,
119581180db9Smartijn AGENTX_CONTEXT_CTX(axc), axr->axr_timeout, axr->axr_priority,
119681180db9Smartijn 0, &(axr->axr_oid), 0);
119781180db9Smartijn if (packetid == 0) {
119881180db9Smartijn agentx_log_axc_warn(axc, "couldn't generate %s",
119981180db9Smartijn ax_pdutype2string(AX_PDU_TYPE_REGISTER));
120081180db9Smartijn agentx_reset(ax);
120181180db9Smartijn return -1;
120281180db9Smartijn }
120381180db9Smartijn agentx_log_axc_info(axc, "region %s: opening",
120481180db9Smartijn ax_oid2string(&(axr->axr_oid)));
120581180db9Smartijn axr->axr_cstate = AX_CSTATE_WAITOPEN;
120681180db9Smartijn return agentx_request(ax, packetid, agentx_region_finalize, axr);
120781180db9Smartijn }
120881180db9Smartijn
120981180db9Smartijn static int
121081180db9Smartijn agentx_region_finalize(struct ax_pdu *pdu, void *cookie)
121181180db9Smartijn {
121281180db9Smartijn struct agentx_region *axr = cookie;
121381180db9Smartijn struct agentx_context *axc = axr->axr_axc;
121481180db9Smartijn struct agentx_index *axi;
121581180db9Smartijn struct agentx_object *axo;
121681180db9Smartijn
121781180db9Smartijn #ifdef AX_DEBUG
121881180db9Smartijn if (axr->axr_cstate != AX_CSTATE_WAITOPEN)
121981180db9Smartijn agentx_log_axc_fatalx(axc, "%s: not expecting region open",
122081180db9Smartijn __func__);
122181180db9Smartijn #endif
122281180db9Smartijn
122381180db9Smartijn if (pdu->ap_payload.ap_response.ap_error == AX_PDU_ERROR_NOERROR) {
122481180db9Smartijn axr->axr_cstate = AX_CSTATE_OPEN;
122581180db9Smartijn agentx_log_axc_info(axc, "region %s: open",
122681180db9Smartijn ax_oid2string(&(axr->axr_oid)));
122781180db9Smartijn } else if (pdu->ap_payload.ap_response.ap_error ==
122881180db9Smartijn AX_PDU_ERROR_DUPLICATEREGISTRATION) {
122981180db9Smartijn axr->axr_cstate = AX_CSTATE_CLOSE;
123081180db9Smartijn /* Try at lower priority: first come first serve */
123181180db9Smartijn if ((++axr->axr_priority) != 0) {
123281180db9Smartijn agentx_log_axc_warnx(axc, "region %s: duplicate, "
123381180db9Smartijn "reducing priority",
123481180db9Smartijn ax_oid2string(&(axr->axr_oid)));
123581180db9Smartijn return agentx_region_start(axr);
123681180db9Smartijn }
123781180db9Smartijn agentx_log_axc_info(axc, "region %s: duplicate, can't "
123881180db9Smartijn "reduce priority, ignoring",
123981180db9Smartijn ax_oid2string(&(axr->axr_oid)));
12408fea2aa4Smartijn } else {
124181180db9Smartijn axr->axr_cstate = AX_CSTATE_CLOSE;
124281180db9Smartijn agentx_log_axc_warnx(axc, "region %s: %s",
124381180db9Smartijn ax_oid2string(&(axr->axr_oid)),
124481180db9Smartijn ax_error2string(pdu->ap_payload.ap_response.ap_error));
124581180db9Smartijn return -1;
124681180db9Smartijn }
124781180db9Smartijn
124881180db9Smartijn if (axr->axr_dstate == AX_DSTATE_CLOSE) {
124981180db9Smartijn if (agentx_region_close(axr) == -1)
125081180db9Smartijn return -1;
125181180db9Smartijn } else {
125281180db9Smartijn TAILQ_FOREACH(axi, &(axr->axr_indices), axi_axr_indices) {
125381180db9Smartijn if (agentx_index_start(axi) == -1)
125481180db9Smartijn return -1;
125581180db9Smartijn }
125681180db9Smartijn TAILQ_FOREACH(axo, &(axr->axr_objects), axo_axr_objects) {
125781180db9Smartijn if (agentx_object_start(axo) == -1)
125881180db9Smartijn return -1;
125981180db9Smartijn }
126081180db9Smartijn }
126181180db9Smartijn return 0;
126281180db9Smartijn }
126381180db9Smartijn
126481180db9Smartijn static int
126581180db9Smartijn agentx_region_close(struct agentx_region *axr)
126681180db9Smartijn {
126781180db9Smartijn struct agentx_context *axc = axr->axr_axc;
126881180db9Smartijn struct agentx_session *axs = axc->axc_axs;
126981180db9Smartijn struct agentx *ax = axs->axs_ax;
127081180db9Smartijn uint32_t packetid;
127181180db9Smartijn
127281180db9Smartijn #ifdef AX_DEBUG
127381180db9Smartijn if (axr->axr_cstate != AX_CSTATE_OPEN)
127481180db9Smartijn agentx_log_axc_fatalx(axc, "%s: unexpected region close",
127581180db9Smartijn __func__);
127681180db9Smartijn #endif
127781180db9Smartijn
127881180db9Smartijn axr->axr_cstate = AX_CSTATE_WAITCLOSE;
127981180db9Smartijn if (axs->axs_cstate == AX_CSTATE_WAITCLOSE)
128081180db9Smartijn return 0;
128181180db9Smartijn
128281180db9Smartijn packetid = ax_unregister(ax->ax_ax, axs->axs_id,
128381180db9Smartijn AGENTX_CONTEXT_CTX(axc), axr->axr_priority, 0, &(axr->axr_oid),
128481180db9Smartijn 0);
128581180db9Smartijn if (packetid == 0) {
128681180db9Smartijn agentx_log_axc_warn(axc, "couldn't generate %s",
128781180db9Smartijn ax_pdutype2string(AX_PDU_TYPE_UNREGISTER));
128881180db9Smartijn agentx_reset(ax);
128981180db9Smartijn return -1;
129081180db9Smartijn }
129181180db9Smartijn agentx_log_axc_info(axc, "region %s: closing",
129281180db9Smartijn ax_oid2string(&(axr->axr_oid)));
129381180db9Smartijn return agentx_request(ax, packetid, agentx_region_close_finalize,
129481180db9Smartijn axr);
129581180db9Smartijn }
129681180db9Smartijn
129781180db9Smartijn static int
129881180db9Smartijn agentx_region_close_finalize(struct ax_pdu *pdu, void *cookie)
129981180db9Smartijn {
130081180db9Smartijn struct agentx_region *axr = cookie;
130181180db9Smartijn struct agentx_context *axc = axr->axr_axc;
130281180db9Smartijn struct agentx_session *axs = axc->axc_axs;
130381180db9Smartijn struct agentx *ax = axs->axs_ax;
1304f00a771dSmartijn int axfree = ax->ax_free;
130581180db9Smartijn
130681180db9Smartijn #ifdef AX_DEBUG
130781180db9Smartijn if (axr->axr_cstate != AX_CSTATE_WAITCLOSE)
130881180db9Smartijn agentx_log_axc_fatalx(axc, "%s: unexpected region close",
130981180db9Smartijn __func__);
131081180db9Smartijn #endif
131181180db9Smartijn
131281180db9Smartijn if (pdu->ap_payload.ap_response.ap_error != AX_PDU_ERROR_NOERROR) {
131381180db9Smartijn agentx_log_axc_warnx(axc, "closing %s: %s",
131481180db9Smartijn ax_oid2string(&(axr->axr_oid)),
131581180db9Smartijn ax_error2string(pdu->ap_payload.ap_response.ap_error));
131681180db9Smartijn agentx_reset(ax);
131781180db9Smartijn return -1;
131881180db9Smartijn }
131981180db9Smartijn
1320f00a771dSmartijn ax->ax_free = 1;
132181180db9Smartijn axr->axr_priority = AX_PRIORITY_DEFAULT;
132281180db9Smartijn axr->axr_cstate = AX_CSTATE_CLOSE;
132381180db9Smartijn
132481180db9Smartijn agentx_log_axc_info(axc, "region %s: closed",
132581180db9Smartijn ax_oid2string(&(axr->axr_oid)));
132681180db9Smartijn
1327f00a771dSmartijn if (axc->axc_cstate == AX_CSTATE_OPEN &&
1328f00a771dSmartijn axr->axr_dstate == AX_DSTATE_OPEN)
1329f00a771dSmartijn agentx_region_start(axr);
1330f00a771dSmartijn
1331f00a771dSmartijn if (!axfree)
1332f00a771dSmartijn agentx_free_finalize(ax);
133381180db9Smartijn return 0;
133481180db9Smartijn }
133581180db9Smartijn
133681180db9Smartijn void
133781180db9Smartijn agentx_region_free(struct agentx_region *axr)
133881180db9Smartijn {
133933598f3aSmartijn struct agentx_index *axi, *taxi;
134033598f3aSmartijn struct agentx_object *axo, *taxo;
1341f00a771dSmartijn struct agentx *ax;
1342f00a771dSmartijn int axfree;
134381180db9Smartijn
134481180db9Smartijn if (axr == NULL)
134581180db9Smartijn return;
134681180db9Smartijn
1347f00a771dSmartijn ax = axr->axr_axc->axc_axs->axs_ax;
1348f00a771dSmartijn axfree = ax->ax_free;
1349f00a771dSmartijn ax->ax_free = 1;
1350f00a771dSmartijn
135181180db9Smartijn if (axr->axr_dstate == AX_DSTATE_CLOSE)
135281180db9Smartijn agentx_log_axc_fatalx(axr->axr_axc, "%s: double free",
135381180db9Smartijn __func__);
135481180db9Smartijn
135581180db9Smartijn axr->axr_dstate = AX_DSTATE_CLOSE;
135681180db9Smartijn
135733598f3aSmartijn TAILQ_FOREACH_SAFE(axi, &(axr->axr_indices), axi_axr_indices, taxi) {
135881180db9Smartijn if (axi->axi_dstate != AX_DSTATE_CLOSE)
135981180db9Smartijn agentx_index_free(axi);
136081180db9Smartijn }
136181180db9Smartijn
136233598f3aSmartijn TAILQ_FOREACH_SAFE(axo, &(axr->axr_objects), axo_axr_objects, taxo) {
136381180db9Smartijn if (axo->axo_dstate != AX_DSTATE_CLOSE)
136481180db9Smartijn agentx_object_free(axo);
136581180db9Smartijn }
136681180db9Smartijn
1367f00a771dSmartijn if (axr->axr_cstate == AX_CSTATE_OPEN)
1368f00a771dSmartijn agentx_region_close(axr);
136981180db9Smartijn
1370f00a771dSmartijn if (!axfree)
1371f00a771dSmartijn agentx_free_finalize(ax);
137281180db9Smartijn }
137381180db9Smartijn
137481180db9Smartijn static void
137581180db9Smartijn agentx_region_free_finalize(struct agentx_region *axr)
137681180db9Smartijn {
137781180db9Smartijn struct agentx_context *axc = axr->axr_axc;
1378f00a771dSmartijn struct agentx_index *axi, *taxi;
1379f00a771dSmartijn struct agentx_object *axo, *taxo;
138081180db9Smartijn
1381f00a771dSmartijn TAILQ_FOREACH_SAFE(axo, &(axr->axr_objects), axo_axr_objects, taxo)
1382f00a771dSmartijn agentx_object_free_finalize(axo);
1383f00a771dSmartijn TAILQ_FOREACH_SAFE(axi, &(axr->axr_indices), axi_axr_indices, taxi)
1384f00a771dSmartijn agentx_index_free_finalize(axi);
138581180db9Smartijn
138681180db9Smartijn if (!TAILQ_EMPTY(&(axr->axr_indices)) ||
1387f00a771dSmartijn !TAILQ_EMPTY(&(axr->axr_objects)) ||
1388f00a771dSmartijn axr->axr_cstate != AX_CSTATE_CLOSE ||
1389f00a771dSmartijn axr->axr_dstate != AX_DSTATE_CLOSE)
139081180db9Smartijn return;
139181180db9Smartijn
139281180db9Smartijn TAILQ_REMOVE(&(axc->axc_regions), axr, axr_axc_regions);
139381180db9Smartijn free(axr);
139481180db9Smartijn }
139581180db9Smartijn
139681180db9Smartijn static void
139781180db9Smartijn agentx_region_reset(struct agentx_region *axr)
139881180db9Smartijn {
139933598f3aSmartijn struct agentx_index *axi, *taxi;
140033598f3aSmartijn struct agentx_object *axo, *taxo;
1401f00a771dSmartijn struct agentx *ax = axr->axr_axc->axc_axs->axs_ax;
1402f00a771dSmartijn int axfree = ax->ax_free;
140381180db9Smartijn
140481180db9Smartijn axr->axr_cstate = AX_CSTATE_CLOSE;
140581180db9Smartijn axr->axr_priority = AX_PRIORITY_DEFAULT;
1406f00a771dSmartijn ax->ax_free = 1;
140781180db9Smartijn
140833598f3aSmartijn TAILQ_FOREACH_SAFE(axi, &(axr->axr_indices), axi_axr_indices, taxi)
140981180db9Smartijn agentx_index_reset(axi);
141033598f3aSmartijn TAILQ_FOREACH_SAFE(axo, &(axr->axr_objects), axo_axr_objects, taxo)
141181180db9Smartijn agentx_object_reset(axo);
141281180db9Smartijn
1413f00a771dSmartijn if (!axfree)
1414f00a771dSmartijn agentx_free_finalize(ax);
141581180db9Smartijn }
141681180db9Smartijn
141781180db9Smartijn struct agentx_index *
141881180db9Smartijn agentx_index_integer_new(struct agentx_region *axr, uint32_t oid[],
141981180db9Smartijn size_t oidlen)
142081180db9Smartijn {
142181180db9Smartijn struct ax_varbind vb;
14229c70cf54Smartijn const char *errstr;
142381180db9Smartijn
14249c70cf54Smartijn vb.avb_type = AX_DATA_TYPE_INTEGER;
14259c70cf54Smartijn if (agentx_oidfill(&(vb.avb_oid), oid, oidlen, &errstr) == -1) {
142681180db9Smartijn #ifdef AX_DEBUG
14279c70cf54Smartijn agentx_log_axc_fatalx(axr->axr_axc, "%s: %s", __func__, errstr);
142881180db9Smartijn #else
14299c70cf54Smartijn agentx_log_axc_warnx(axr->axr_axc, "%s: %s", __func__, errstr);
143081180db9Smartijn return NULL;
143181180db9Smartijn #endif
143281180db9Smartijn }
14331b6ededeSmartijn vb.avb_data.avb_int32 = 0;
143481180db9Smartijn
143581180db9Smartijn return agentx_index(axr, &vb, AXI_TYPE_NEW);
143681180db9Smartijn }
143781180db9Smartijn
143881180db9Smartijn struct agentx_index *
143981180db9Smartijn agentx_index_integer_any(struct agentx_region *axr, uint32_t oid[],
144081180db9Smartijn size_t oidlen)
144181180db9Smartijn {
144281180db9Smartijn struct ax_varbind vb;
14439c70cf54Smartijn const char *errstr;
144481180db9Smartijn
14459c70cf54Smartijn vb.avb_type = AX_DATA_TYPE_INTEGER;
14469c70cf54Smartijn if (agentx_oidfill(&(vb.avb_oid), oid, oidlen, &errstr) == -1) {
144781180db9Smartijn #ifdef AX_DEBUG
14489c70cf54Smartijn agentx_log_axc_fatalx(axr->axr_axc, "%s: %s", __func__, errstr);
144981180db9Smartijn #else
14509c70cf54Smartijn agentx_log_axc_warnx(axr->axr_axc, "%s: %s", __func__, errstr);
145181180db9Smartijn return NULL;
145281180db9Smartijn #endif
145381180db9Smartijn }
14541b6ededeSmartijn vb.avb_data.avb_int32 = 0;
145581180db9Smartijn
145681180db9Smartijn return agentx_index(axr, &vb, AXI_TYPE_ANY);
145781180db9Smartijn }
145881180db9Smartijn
145981180db9Smartijn struct agentx_index *
146081180db9Smartijn agentx_index_integer_value(struct agentx_region *axr, uint32_t oid[],
14611b6ededeSmartijn size_t oidlen, int32_t value)
146281180db9Smartijn {
146381180db9Smartijn struct ax_varbind vb;
14649c70cf54Smartijn const char *errstr;
146581180db9Smartijn
14661b6ededeSmartijn if (value < 0) {
14671b6ededeSmartijn #ifdef AX_DEBUG
14681b6ededeSmartijn agentx_log_axc_fatalx(axr->axr_axc, "%s: value < 0", __func__);
14691b6ededeSmartijn #else
14701b6ededeSmartijn agentx_log_axc_warnx(axr->axr_axc, "%s: value < 0", __func__);
14711b6ededeSmartijn errno = EINVAL;
14721b6ededeSmartijn return NULL;
14731b6ededeSmartijn #endif
14741b6ededeSmartijn }
147581180db9Smartijn
147681180db9Smartijn vb.avb_type = AX_DATA_TYPE_INTEGER;
14779c70cf54Smartijn if (agentx_oidfill(&(vb.avb_oid), oid, oidlen, &errstr) == -1) {
14789c70cf54Smartijn #ifdef AX_DEBUG
14799c70cf54Smartijn agentx_log_axc_fatalx(axr->axr_axc, "%s: %s", __func__, errstr);
14809c70cf54Smartijn #else
14819c70cf54Smartijn agentx_log_axc_warnx(axr->axr_axc, "%s: %s", __func__, errstr);
14829c70cf54Smartijn return NULL;
14839c70cf54Smartijn #endif
14849c70cf54Smartijn }
14851b6ededeSmartijn vb.avb_data.avb_int32 = value;
148681180db9Smartijn
148781180db9Smartijn return agentx_index(axr, &vb, AXI_TYPE_VALUE);
148881180db9Smartijn }
148981180db9Smartijn
149081180db9Smartijn struct agentx_index *
149181180db9Smartijn agentx_index_integer_dynamic(struct agentx_region *axr, uint32_t oid[],
149281180db9Smartijn size_t oidlen)
149381180db9Smartijn {
149481180db9Smartijn struct ax_varbind vb;
14959c70cf54Smartijn const char *errstr;
149681180db9Smartijn
14979c70cf54Smartijn vb.avb_type = AX_DATA_TYPE_INTEGER;
14989c70cf54Smartijn if (agentx_oidfill(&(vb.avb_oid), oid, oidlen, &errstr) == -1) {
149981180db9Smartijn #ifdef AX_DEBUG
15009c70cf54Smartijn agentx_log_axc_fatalx(axr->axr_axc, "%s: %s", __func__, errstr);
150181180db9Smartijn #else
15029c70cf54Smartijn agentx_log_axc_warnx(axr->axr_axc, "%s: %s", __func__, errstr);
150381180db9Smartijn return NULL;
150481180db9Smartijn #endif
150581180db9Smartijn }
150681180db9Smartijn
150781180db9Smartijn return agentx_index(axr, &vb, AXI_TYPE_DYNAMIC);
150881180db9Smartijn }
150981180db9Smartijn
151081180db9Smartijn struct agentx_index *
151181180db9Smartijn agentx_index_string_dynamic(struct agentx_region *axr, uint32_t oid[],
151281180db9Smartijn size_t oidlen)
151381180db9Smartijn {
151481180db9Smartijn struct ax_varbind vb;
15159c70cf54Smartijn const char *errstr;
151681180db9Smartijn
15179c70cf54Smartijn vb.avb_type = AX_DATA_TYPE_OCTETSTRING;
15189c70cf54Smartijn if (agentx_oidfill(&(vb.avb_oid), oid, oidlen, &errstr) == -1) {
151981180db9Smartijn #ifdef AX_DEBUG
15209c70cf54Smartijn agentx_log_axc_fatalx(axr->axr_axc, "%s: %s", __func__, errstr);
152181180db9Smartijn #else
15229c70cf54Smartijn agentx_log_axc_warnx(axr->axr_axc, "%s: %s", __func__, errstr);
152381180db9Smartijn return NULL;
152481180db9Smartijn #endif
152581180db9Smartijn }
152681180db9Smartijn vb.avb_data.avb_ostring.aos_slen = 0;
152781180db9Smartijn vb.avb_data.avb_ostring.aos_string = NULL;
152881180db9Smartijn
152981180db9Smartijn return agentx_index(axr, &vb, AXI_TYPE_DYNAMIC);
153081180db9Smartijn }
153181180db9Smartijn
153281180db9Smartijn struct agentx_index *
153381180db9Smartijn agentx_index_nstring_dynamic(struct agentx_region *axr, uint32_t oid[],
153481180db9Smartijn size_t oidlen, size_t vlen)
153581180db9Smartijn {
153681180db9Smartijn struct ax_varbind vb;
15379c70cf54Smartijn const char *errstr;
153881180db9Smartijn
153981180db9Smartijn if (vlen == 0 || vlen > AGENTX_OID_MAX_LEN) {
154081180db9Smartijn #ifdef AX_DEBUG
154181180db9Smartijn agentx_log_axc_fatalx(axr->axr_axc, "%s: invalid string "
154281180db9Smartijn "length: %zu\n", __func__, vlen);
154381180db9Smartijn #else
154481180db9Smartijn agentx_log_axc_warnx(axr->axr_axc, "%s: invalid string "
154581180db9Smartijn "length: %zu\n", __func__, vlen);
154681180db9Smartijn errno = EINVAL;
154781180db9Smartijn return NULL;
154881180db9Smartijn #endif
154981180db9Smartijn }
155081180db9Smartijn
155181180db9Smartijn vb.avb_type = AX_DATA_TYPE_OCTETSTRING;
15529c70cf54Smartijn if (agentx_oidfill(&(vb.avb_oid), oid, oidlen, &errstr) == -1) {
15539c70cf54Smartijn #ifdef AX_DEBUG
15549c70cf54Smartijn agentx_log_axc_fatalx(axr->axr_axc, "%s: %s", __func__, errstr);
15559c70cf54Smartijn #else
15569c70cf54Smartijn agentx_log_axc_warnx(axr->axr_axc, "%s: %s", __func__, errstr);
15579c70cf54Smartijn return NULL;
15589c70cf54Smartijn #endif
15599c70cf54Smartijn }
156081180db9Smartijn vb.avb_data.avb_ostring.aos_slen = vlen;
156181180db9Smartijn vb.avb_data.avb_ostring.aos_string = NULL;
156281180db9Smartijn
156381180db9Smartijn return agentx_index(axr, &vb, AXI_TYPE_DYNAMIC);
156481180db9Smartijn }
156581180db9Smartijn
156681180db9Smartijn struct agentx_index *
156781180db9Smartijn agentx_index_oid_dynamic(struct agentx_region *axr, uint32_t oid[],
156881180db9Smartijn size_t oidlen)
156981180db9Smartijn {
157081180db9Smartijn struct ax_varbind vb;
15719c70cf54Smartijn const char *errstr;
157281180db9Smartijn
15739c70cf54Smartijn vb.avb_type = AX_DATA_TYPE_OID;
15749c70cf54Smartijn if (agentx_oidfill(&(vb.avb_oid), oid, oidlen, &errstr) == -1) {
157581180db9Smartijn #ifdef AX_DEBUG
15769c70cf54Smartijn agentx_log_axc_fatalx(axr->axr_axc, "%s: %s", __func__, errstr);
157781180db9Smartijn #else
15789c70cf54Smartijn agentx_log_axc_warnx(axr->axr_axc, "%s: %s", __func__, errstr);
157981180db9Smartijn return NULL;
158081180db9Smartijn #endif
158181180db9Smartijn }
158281180db9Smartijn vb.avb_data.avb_oid.aoi_idlen = 0;
158381180db9Smartijn
158481180db9Smartijn return agentx_index(axr, &vb, AXI_TYPE_DYNAMIC);
158581180db9Smartijn }
158681180db9Smartijn
158781180db9Smartijn struct agentx_index *
158881180db9Smartijn agentx_index_noid_dynamic(struct agentx_region *axr, uint32_t oid[],
158981180db9Smartijn size_t oidlen, size_t vlen)
159081180db9Smartijn {
159181180db9Smartijn struct ax_varbind vb;
15929c70cf54Smartijn const char *errstr;
159381180db9Smartijn
15949c70cf54Smartijn if (vlen < AGENTX_OID_MIN_LEN || vlen > AGENTX_OID_MAX_LEN) {
159581180db9Smartijn #ifdef AX_DEBUG
159681180db9Smartijn agentx_log_axc_fatalx(axr->axr_axc, "%s: invalid string "
159781180db9Smartijn "length: %zu\n", __func__, vlen);
159881180db9Smartijn #else
159981180db9Smartijn agentx_log_axc_warnx(axr->axr_axc, "%s: invalid string "
160081180db9Smartijn "length: %zu\n", __func__, vlen);
160181180db9Smartijn errno = EINVAL;
160281180db9Smartijn return NULL;
160381180db9Smartijn #endif
160481180db9Smartijn }
160581180db9Smartijn
160681180db9Smartijn vb.avb_type = AX_DATA_TYPE_OID;
16079c70cf54Smartijn if (agentx_oidfill(&(vb.avb_oid), oid, oidlen, &errstr) == -1) {
16089c70cf54Smartijn #ifdef AX_DEBUG
16099c70cf54Smartijn agentx_log_axc_fatalx(axr->axr_axc, "%s: %s", __func__, errstr);
16109c70cf54Smartijn #else
16119c70cf54Smartijn agentx_log_axc_warnx(axr->axr_axc, "%s: %s", __func__, errstr);
16129c70cf54Smartijn return NULL;
16139c70cf54Smartijn #endif
16149c70cf54Smartijn }
161581180db9Smartijn vb.avb_data.avb_oid.aoi_idlen = vlen;
161681180db9Smartijn
161781180db9Smartijn return agentx_index(axr, &vb, AXI_TYPE_DYNAMIC);
161881180db9Smartijn }
161981180db9Smartijn
162081180db9Smartijn struct agentx_index *
162181180db9Smartijn agentx_index_ipaddress_dynamic(struct agentx_region *axr, uint32_t oid[],
162281180db9Smartijn size_t oidlen)
162381180db9Smartijn {
162481180db9Smartijn struct ax_varbind vb;
16259c70cf54Smartijn const char *errstr;
162681180db9Smartijn
16279c70cf54Smartijn vb.avb_type = AX_DATA_TYPE_IPADDRESS;
16289c70cf54Smartijn if (agentx_oidfill(&(vb.avb_oid), oid, oidlen, &errstr) == -1) {
162981180db9Smartijn #ifdef AX_DEBUG
16309c70cf54Smartijn agentx_log_axc_fatalx(axr->axr_axc, "%s: %s", __func__, errstr);
163181180db9Smartijn #else
16329c70cf54Smartijn agentx_log_axc_warnx(axr->axr_axc, "%s: %s", __func__, errstr);
163381180db9Smartijn return NULL;
163481180db9Smartijn #endif
163581180db9Smartijn }
163681180db9Smartijn vb.avb_data.avb_ostring.aos_string = NULL;
163781180db9Smartijn
163881180db9Smartijn return agentx_index(axr, &vb, AXI_TYPE_DYNAMIC);
163981180db9Smartijn }
164081180db9Smartijn
164181180db9Smartijn static struct agentx_index *
164281180db9Smartijn agentx_index(struct agentx_region *axr, struct ax_varbind *vb,
164381180db9Smartijn enum agentx_index_type type)
164481180db9Smartijn {
164581180db9Smartijn struct agentx_index *axi;
164681180db9Smartijn
164781180db9Smartijn if (axr->axr_dstate == AX_DSTATE_CLOSE)
164881180db9Smartijn agentx_log_axc_fatalx(axr->axr_axc, "%s: use after free",
164981180db9Smartijn __func__);
165081180db9Smartijn if (ax_oid_cmp(&(axr->axr_oid), &(vb->avb_oid)) != -2) {
165181180db9Smartijn #ifdef AX_DEBUG
165281180db9Smartijn agentx_log_axc_fatalx(axr->axr_axc, "%s: oid is not child "
165381180db9Smartijn "of region %s", __func__,
165481180db9Smartijn ax_oid2string(&(vb->avb_oid)));
165581180db9Smartijn #else
165681180db9Smartijn agentx_log_axc_warnx(axr->axr_axc, "%s: oid is not child of "
165781180db9Smartijn "region %s", __func__, ax_oid2string(&(vb->avb_oid)));
165881180db9Smartijn errno = EINVAL;
165981180db9Smartijn return NULL;
166081180db9Smartijn #endif
166181180db9Smartijn }
166281180db9Smartijn
166381180db9Smartijn if ((axi = calloc(1, sizeof(*axi))) == NULL)
166481180db9Smartijn return NULL;
166581180db9Smartijn
166681180db9Smartijn axi->axi_axr = axr;
166781180db9Smartijn axi->axi_type = type;
166881180db9Smartijn bcopy(vb, &(axi->axi_vb), sizeof(*vb));
166981180db9Smartijn axi->axi_cstate = AX_CSTATE_CLOSE;
167081180db9Smartijn axi->axi_dstate = AX_DSTATE_OPEN;
167181180db9Smartijn TAILQ_INSERT_HEAD(&(axr->axr_indices), axi, axi_axr_indices);
167281180db9Smartijn
167381180db9Smartijn if (axr->axr_cstate == AX_CSTATE_OPEN)
167481180db9Smartijn agentx_index_start(axi);
167581180db9Smartijn
167681180db9Smartijn return axi;
167781180db9Smartijn }
167881180db9Smartijn
167981180db9Smartijn static int
168081180db9Smartijn agentx_index_start(struct agentx_index *axi)
168181180db9Smartijn {
168281180db9Smartijn struct agentx_region *axr = axi->axi_axr;
168381180db9Smartijn struct agentx_context *axc = axr->axr_axc;
168481180db9Smartijn struct agentx_session *axs = axc->axc_axs;
168581180db9Smartijn struct agentx *ax = axs->axs_ax;
168681180db9Smartijn uint32_t packetid;
168781180db9Smartijn int flags = 0;
168881180db9Smartijn
168981180db9Smartijn #ifdef AX_DEBUG
169081180db9Smartijn if (axr->axr_cstate != AX_CSTATE_OPEN ||
169181180db9Smartijn axi->axi_cstate != AX_CSTATE_CLOSE ||
169281180db9Smartijn axi->axi_dstate != AX_DSTATE_OPEN)
169381180db9Smartijn agentx_log_axc_fatalx(axc, "%s: unexpected index allocation",
169481180db9Smartijn __func__);
169581180db9Smartijn #endif
169681180db9Smartijn
169781180db9Smartijn axi->axi_cstate = AX_CSTATE_WAITOPEN;
169881180db9Smartijn
169981180db9Smartijn if (axi->axi_type == AXI_TYPE_NEW)
170081180db9Smartijn flags = AX_PDU_FLAG_NEW_INDEX;
170181180db9Smartijn else if (axi->axi_type == AXI_TYPE_ANY)
170281180db9Smartijn flags = AX_PDU_FLAG_ANY_INDEX;
170381180db9Smartijn else if (axi->axi_type == AXI_TYPE_DYNAMIC) {
170481180db9Smartijn agentx_index_finalize(NULL, axi);
170581180db9Smartijn return 0;
170681180db9Smartijn }
170781180db9Smartijn
170881180db9Smartijn /* We might be able to bundle, but if we fail we'd have to reorganise */
170981180db9Smartijn packetid = ax_indexallocate(ax->ax_ax, flags, axs->axs_id,
171081180db9Smartijn AGENTX_CONTEXT_CTX(axc), &(axi->axi_vb), 1);
171181180db9Smartijn if (packetid == 0) {
171281180db9Smartijn agentx_log_axc_warn(axc, "couldn't generate %s",
171381180db9Smartijn ax_pdutype2string(AX_PDU_TYPE_INDEXDEALLOCATE));
171481180db9Smartijn agentx_reset(ax);
171581180db9Smartijn return -1;
171681180db9Smartijn }
171781180db9Smartijn if (axi->axi_type == AXI_TYPE_VALUE)
17181b6ededeSmartijn agentx_log_axc_info(axc, "index %s: allocating '%d'",
171981180db9Smartijn ax_oid2string(&(axi->axi_vb.avb_oid)),
17201b6ededeSmartijn axi->axi_vb.avb_data.avb_int32);
172181180db9Smartijn else if (axi->axi_type == AXI_TYPE_ANY)
172281180db9Smartijn agentx_log_axc_info(axc, "index %s: allocating any index",
172381180db9Smartijn ax_oid2string(&(axi->axi_vb.avb_oid)));
172481180db9Smartijn else if (axi->axi_type == AXI_TYPE_NEW)
172581180db9Smartijn agentx_log_axc_info(axc, "index %s: allocating new index",
172681180db9Smartijn ax_oid2string(&(axi->axi_vb.avb_oid)));
172781180db9Smartijn
172881180db9Smartijn return agentx_request(ax, packetid, agentx_index_finalize, axi);
172981180db9Smartijn }
173081180db9Smartijn
173181180db9Smartijn static int
173281180db9Smartijn agentx_index_finalize(struct ax_pdu *pdu, void *cookie)
173381180db9Smartijn {
173481180db9Smartijn struct agentx_index *axi = cookie;
173581180db9Smartijn struct agentx_region *axr = axi->axi_axr;
173681180db9Smartijn struct agentx_context *axc = axr->axr_axc;
173781180db9Smartijn struct ax_pdu_response *resp;
173881180db9Smartijn size_t i;
173981180db9Smartijn
174081180db9Smartijn #ifdef AX_DEBUG
174181180db9Smartijn if (axi->axi_cstate != AX_CSTATE_WAITOPEN)
174281180db9Smartijn agentx_log_axc_fatalx(axc,
174381180db9Smartijn "%s: not expecting index allocate", __func__);
174481180db9Smartijn #endif
174581180db9Smartijn if (axi->axi_type == AXI_TYPE_DYNAMIC) {
174681180db9Smartijn axi->axi_cstate = AX_CSTATE_OPEN;
1747cb11ee67Smartijn goto objects_start;
174881180db9Smartijn }
174981180db9Smartijn
175081180db9Smartijn resp = &(pdu->ap_payload.ap_response);
175181180db9Smartijn if (resp->ap_error != AX_PDU_ERROR_NOERROR) {
175281180db9Smartijn axi->axi_cstate = AX_CSTATE_CLOSE;
175381180db9Smartijn agentx_log_axc_warnx(axc, "index %s: %s",
175481180db9Smartijn ax_oid2string(&(axr->axr_oid)),
175581180db9Smartijn ax_error2string(resp->ap_error));
175681180db9Smartijn return 0;
175781180db9Smartijn }
175881180db9Smartijn axi->axi_cstate = AX_CSTATE_OPEN;
175981180db9Smartijn if (resp->ap_nvarbind != 1) {
176081180db9Smartijn agentx_log_axc_warnx(axc, "index %s: unexpected number of "
176181180db9Smartijn "indices", ax_oid2string(&(axr->axr_oid)));
17628fea2aa4Smartijn axi->axi_cstate = AX_CSTATE_CLOSE;
176381180db9Smartijn return -1;
176481180db9Smartijn }
176581180db9Smartijn if (resp->ap_varbindlist[0].avb_type != axi->axi_vb.avb_type) {
176681180db9Smartijn agentx_log_axc_warnx(axc, "index %s: unexpected index type",
176781180db9Smartijn ax_oid2string(&(axr->axr_oid)));
17688fea2aa4Smartijn axi->axi_cstate = AX_CSTATE_CLOSE;
176981180db9Smartijn return -1;
177081180db9Smartijn }
177181180db9Smartijn if (ax_oid_cmp(&(resp->ap_varbindlist[0].avb_oid),
177281180db9Smartijn &(axi->axi_vb.avb_oid)) != 0) {
177381180db9Smartijn agentx_log_axc_warnx(axc, "index %s: unexpected oid",
177481180db9Smartijn ax_oid2string(&(axr->axr_oid)));
17758fea2aa4Smartijn axi->axi_cstate = AX_CSTATE_CLOSE;
177681180db9Smartijn return -1;
177781180db9Smartijn }
177881180db9Smartijn
177981180db9Smartijn switch (axi->axi_vb.avb_type) {
178081180db9Smartijn case AX_DATA_TYPE_INTEGER:
178181180db9Smartijn if (axi->axi_type == AXI_TYPE_NEW ||
178281180db9Smartijn axi->axi_type == AXI_TYPE_ANY)
17831b6ededeSmartijn axi->axi_vb.avb_data.avb_int32 =
17841b6ededeSmartijn resp->ap_varbindlist[0].avb_data.avb_int32;
17851b6ededeSmartijn else if (axi->axi_vb.avb_data.avb_int32 !=
17861b6ededeSmartijn resp->ap_varbindlist[0].avb_data.avb_int32) {
178781180db9Smartijn agentx_log_axc_warnx(axc, "index %s: unexpected "
178881180db9Smartijn "index value", ax_oid2string(&(axr->axr_oid)));
17898fea2aa4Smartijn axi->axi_cstate = AX_CSTATE_CLOSE;
179081180db9Smartijn return -1;
179181180db9Smartijn }
17921b6ededeSmartijn agentx_log_axc_info(axc, "index %s: allocated '%d'",
179381180db9Smartijn ax_oid2string(&(axi->axi_vb.avb_oid)),
17941b6ededeSmartijn axi->axi_vb.avb_data.avb_int32);
179581180db9Smartijn break;
179681180db9Smartijn default:
179781180db9Smartijn agentx_log_axc_fatalx(axc, "%s: Unsupported index type",
179881180db9Smartijn __func__);
179981180db9Smartijn }
180081180db9Smartijn
180181180db9Smartijn if (axi->axi_dstate == AX_DSTATE_CLOSE)
180281180db9Smartijn return agentx_index_close(axi);
180381180db9Smartijn
1804cb11ee67Smartijn objects_start:
180581180db9Smartijn /* TODO Make use of range_subid register */
180681180db9Smartijn for (i = 0; i < axi->axi_objectlen; i++) {
180781180db9Smartijn if (axi->axi_object[i]->axo_dstate == AX_DSTATE_OPEN) {
180881180db9Smartijn if (agentx_object_start(axi->axi_object[i]) == -1)
180981180db9Smartijn return -1;
181081180db9Smartijn }
181181180db9Smartijn }
181281180db9Smartijn return 0;
181381180db9Smartijn }
181481180db9Smartijn
181581180db9Smartijn void
181681180db9Smartijn agentx_index_free(struct agentx_index *axi)
181781180db9Smartijn {
181881180db9Smartijn size_t i;
181981180db9Smartijn struct agentx_object *axo;
1820f00a771dSmartijn struct agentx *ax;
1821f00a771dSmartijn int axfree;
182281180db9Smartijn
182381180db9Smartijn if (axi == NULL)
182481180db9Smartijn return;
182581180db9Smartijn
1826f00a771dSmartijn ax = axi->axi_axr->axr_axc->axc_axs->axs_ax;
1827f00a771dSmartijn axfree = ax->ax_free;
1828f00a771dSmartijn ax->ax_free = 1;
1829f00a771dSmartijn
183081180db9Smartijn if (axi->axi_dstate == AX_DSTATE_CLOSE)
183181180db9Smartijn agentx_log_axc_fatalx(axi->axi_axr->axr_axc,
183281180db9Smartijn "%s: double free", __func__);
183381180db9Smartijn
183481180db9Smartijn /* TODO Do a range_subid unregister before freeing */
183581180db9Smartijn for (i = 0; i < axi->axi_objectlen; i++) {
183681180db9Smartijn axo = axi->axi_object[i];
183781180db9Smartijn if (axo->axo_dstate != AX_DSTATE_CLOSE) {
183881180db9Smartijn agentx_object_free(axo);
183981180db9Smartijn if (axi->axi_object[i] != axo)
184081180db9Smartijn i--;
184181180db9Smartijn }
184281180db9Smartijn }
184381180db9Smartijn
184481180db9Smartijn axi->axi_dstate = AX_DSTATE_CLOSE;
184581180db9Smartijn
184681180db9Smartijn if (axi->axi_cstate == AX_CSTATE_OPEN)
184781180db9Smartijn (void) agentx_index_close(axi);
1848f00a771dSmartijn if (!axfree)
1849f00a771dSmartijn agentx_free_finalize(ax);
185081180db9Smartijn }
185181180db9Smartijn
185281180db9Smartijn static void
185381180db9Smartijn agentx_index_free_finalize(struct agentx_index *axi)
185481180db9Smartijn {
185581180db9Smartijn struct agentx_region *axr = axi->axi_axr;
185681180db9Smartijn
1857f00a771dSmartijn if (axi->axi_cstate != AX_CSTATE_CLOSE ||
1858f00a771dSmartijn axi->axi_dstate != AX_DSTATE_CLOSE ||
1859f00a771dSmartijn axi->axi_objectlen != 0)
186081180db9Smartijn return;
186181180db9Smartijn
186281180db9Smartijn TAILQ_REMOVE(&(axr->axr_indices), axi, axi_axr_indices);
186381180db9Smartijn ax_varbind_free(&(axi->axi_vb));
186481180db9Smartijn free(axi->axi_object);
186581180db9Smartijn free(axi);
186681180db9Smartijn }
186781180db9Smartijn
186881180db9Smartijn static void
186981180db9Smartijn agentx_index_reset(struct agentx_index *axi)
187081180db9Smartijn {
1871f00a771dSmartijn struct agentx *ax = axi->axi_axr->axr_axc->axc_axs->axs_ax;
1872f00a771dSmartijn
187381180db9Smartijn axi->axi_cstate = AX_CSTATE_CLOSE;
187481180db9Smartijn
1875f00a771dSmartijn if (!ax->ax_free)
1876f00a771dSmartijn agentx_free_finalize(ax);
187781180db9Smartijn }
187881180db9Smartijn
187981180db9Smartijn static int
188081180db9Smartijn agentx_index_close(struct agentx_index *axi)
188181180db9Smartijn {
188281180db9Smartijn struct agentx_region *axr = axi->axi_axr;
188381180db9Smartijn struct agentx_context *axc = axr->axr_axc;
188481180db9Smartijn struct agentx_session *axs = axc->axc_axs;
188581180db9Smartijn struct agentx *ax = axs->axs_ax;
188681180db9Smartijn uint32_t packetid;
188781180db9Smartijn
188881180db9Smartijn #ifdef AX_DEBUG
188981180db9Smartijn if (axi->axi_cstate != AX_CSTATE_OPEN)
189081180db9Smartijn agentx_log_axc_fatalx(axc,
189181180db9Smartijn "%s: unexpected index deallocation", __func__);
189281180db9Smartijn #endif
189381180db9Smartijn
189481180db9Smartijn axi->axi_cstate = AX_CSTATE_WAITCLOSE;
189581180db9Smartijn if (axs->axs_cstate == AX_CSTATE_WAITCLOSE)
189681180db9Smartijn return 0;
189781180db9Smartijn
189881180db9Smartijn /* We might be able to bundle, but if we fail we'd have to reorganise */
189981180db9Smartijn packetid = ax_indexdeallocate(ax->ax_ax, axs->axs_id,
190081180db9Smartijn AGENTX_CONTEXT_CTX(axc), &(axi->axi_vb), 1);
190181180db9Smartijn if (packetid == 0) {
190281180db9Smartijn agentx_log_axc_warn(axc, "couldn't generate %s",
190381180db9Smartijn ax_pdutype2string(AX_PDU_TYPE_INDEXDEALLOCATE));
190481180db9Smartijn agentx_reset(ax);
190581180db9Smartijn return -1;
190681180db9Smartijn }
190781180db9Smartijn agentx_log_axc_info(axc, "index %s: deallocating",
190881180db9Smartijn ax_oid2string(&(axi->axi_vb.avb_oid)));
190981180db9Smartijn return agentx_request(ax, packetid, agentx_index_close_finalize,
191081180db9Smartijn axi);
191181180db9Smartijn }
191281180db9Smartijn
191381180db9Smartijn static int
191481180db9Smartijn agentx_index_close_finalize(struct ax_pdu *pdu, void *cookie)
191581180db9Smartijn {
191681180db9Smartijn struct agentx_index *axi = cookie;
191781180db9Smartijn struct agentx_region *axr = axi->axi_axr;
191881180db9Smartijn struct agentx_context *axc = axr->axr_axc;
191981180db9Smartijn struct agentx_session *axs = axc->axc_axs;
192081180db9Smartijn struct agentx *ax = axs->axs_ax;
192181180db9Smartijn struct ax_pdu_response *resp = &(pdu->ap_payload.ap_response);
1922f00a771dSmartijn int axfree = ax->ax_free;
192381180db9Smartijn
192481180db9Smartijn #ifdef AX_DEBUG
192581180db9Smartijn if (axi->axi_cstate != AX_CSTATE_WAITCLOSE)
192681180db9Smartijn agentx_log_axc_fatalx(axc, "%s: unexpected indexdeallocate",
192781180db9Smartijn __func__);
192881180db9Smartijn #endif
192981180db9Smartijn
193081180db9Smartijn if (pdu->ap_payload.ap_response.ap_error != AX_PDU_ERROR_NOERROR) {
193181180db9Smartijn agentx_log_axc_warnx(axc,
193281180db9Smartijn "index %s: couldn't deallocate: %s",
193381180db9Smartijn ax_oid2string(&(axi->axi_vb.avb_oid)),
193481180db9Smartijn ax_error2string(resp->ap_error));
193581180db9Smartijn agentx_reset(ax);
193681180db9Smartijn return -1;
193781180db9Smartijn }
193881180db9Smartijn
193981180db9Smartijn if (resp->ap_nvarbind != 1) {
194081180db9Smartijn agentx_log_axc_warnx(axc,
194181180db9Smartijn "index %s: unexpected number of indices",
194281180db9Smartijn ax_oid2string(&(axr->axr_oid)));
194381180db9Smartijn agentx_reset(ax);
194481180db9Smartijn return -1;
194581180db9Smartijn }
194681180db9Smartijn if (resp->ap_varbindlist[0].avb_type != axi->axi_vb.avb_type) {
194781180db9Smartijn agentx_log_axc_warnx(axc, "index %s: unexpected index type",
194881180db9Smartijn ax_oid2string(&(axr->axr_oid)));
194981180db9Smartijn agentx_reset(ax);
195081180db9Smartijn return -1;
195181180db9Smartijn }
195281180db9Smartijn if (ax_oid_cmp(&(resp->ap_varbindlist[0].avb_oid),
195381180db9Smartijn &(axi->axi_vb.avb_oid)) != 0) {
195481180db9Smartijn agentx_log_axc_warnx(axc, "index %s: unexpected oid",
195581180db9Smartijn ax_oid2string(&(axr->axr_oid)));
195681180db9Smartijn agentx_reset(ax);
195781180db9Smartijn return -1;
195881180db9Smartijn }
195981180db9Smartijn switch (axi->axi_vb.avb_type) {
196081180db9Smartijn case AX_DATA_TYPE_INTEGER:
19611b6ededeSmartijn if (axi->axi_vb.avb_data.avb_int32 !=
19621b6ededeSmartijn resp->ap_varbindlist[0].avb_data.avb_int32) {
196381180db9Smartijn agentx_log_axc_warnx(axc,
196481180db9Smartijn "index %s: unexpected index value",
196581180db9Smartijn ax_oid2string(&(axr->axr_oid)));
196681180db9Smartijn agentx_reset(ax);
196781180db9Smartijn return -1;
196881180db9Smartijn }
196981180db9Smartijn break;
197081180db9Smartijn default:
197181180db9Smartijn agentx_log_axc_fatalx(axc, "%s: Unsupported index type",
197281180db9Smartijn __func__);
197381180db9Smartijn }
197481180db9Smartijn
197581180db9Smartijn axi->axi_cstate = AX_CSTATE_CLOSE;
1976f00a771dSmartijn ax->ax_free = 1;
197781180db9Smartijn
197881180db9Smartijn agentx_log_axc_info(axc, "index %s: deallocated",
197981180db9Smartijn ax_oid2string(&(axi->axi_vb.avb_oid)));
198081180db9Smartijn
1981f00a771dSmartijn if (axr->axr_cstate == AX_CSTATE_OPEN &&
1982f00a771dSmartijn axi->axi_dstate == AX_DSTATE_OPEN)
1983f00a771dSmartijn agentx_index_start(axi);
1984f00a771dSmartijn
1985f00a771dSmartijn if (!axfree)
1986f00a771dSmartijn agentx_free_finalize(ax);
198781180db9Smartijn return 0;
198881180db9Smartijn }
198981180db9Smartijn
199081180db9Smartijn struct agentx_object *
199181180db9Smartijn agentx_object(struct agentx_region *axr, uint32_t oid[], size_t oidlen,
199281180db9Smartijn struct agentx_index *axi[], size_t axilen, int implied,
199381180db9Smartijn void (*get)(struct agentx_varbind *))
199481180db9Smartijn {
199533598f3aSmartijn struct agentx_object *axo, **taxo, axo_search;
199633598f3aSmartijn struct agentx_index *laxi;
19979c70cf54Smartijn const char *errstr;
199881180db9Smartijn int ready = 1;
199981180db9Smartijn size_t i, j;
200081180db9Smartijn
200181180db9Smartijn if (axr->axr_dstate == AX_DSTATE_CLOSE)
200281180db9Smartijn agentx_log_axc_fatalx(axr->axr_axc, "%s: use after free",
200381180db9Smartijn __func__);
200481180db9Smartijn if (axilen > AGENTX_OID_INDEX_MAX_LEN) {
200581180db9Smartijn #ifdef AX_DEBUG
200681180db9Smartijn agentx_log_axc_fatalx(axr->axr_axc, "%s: indexlen > %d",
200781180db9Smartijn __func__, AGENTX_OID_INDEX_MAX_LEN);
200881180db9Smartijn #else
200981180db9Smartijn agentx_log_axc_warnx(axr->axr_axc, "%s: indexlen > %d",
201081180db9Smartijn __func__, AGENTX_OID_INDEX_MAX_LEN);
201181180db9Smartijn errno = EINVAL;
201281180db9Smartijn return NULL;
201381180db9Smartijn #endif
201481180db9Smartijn }
201581180db9Smartijn
20169c70cf54Smartijn if (agentx_oidfill(&(axo_search.axo_oid), oid, oidlen, &errstr) == -1) {
20179c70cf54Smartijn #ifdef AX_DEBUG
20189c70cf54Smartijn agentx_log_axc_fatalx(axr->axr_axc, "%s: %s", __func__, errstr);
20199c70cf54Smartijn #else
20209c70cf54Smartijn agentx_log_axc_warnx(axr->axr_axc, "%s: %s", __func__, errstr);
20219c70cf54Smartijn return NULL;
20229c70cf54Smartijn #endif
20239c70cf54Smartijn }
202481180db9Smartijn
20259dbe2cd1Smartijn do {
202681180db9Smartijn if (RB_FIND(axc_objects, &(axr->axr_axc->axc_objects),
202781180db9Smartijn &axo_search) != NULL) {
202881180db9Smartijn #ifdef AX_DEBUG
202981180db9Smartijn agentx_log_axc_fatalx(axr->axr_axc, "%s: invalid "
203081180db9Smartijn "parent child object relationship", __func__);
203181180db9Smartijn #else
203281180db9Smartijn agentx_log_axc_warnx(axr->axr_axc, "%s: invalid "
203381180db9Smartijn "parent child object relationship", __func__);
20349dbe2cd1Smartijn errno = EINVAL;
203581180db9Smartijn return NULL;
203681180db9Smartijn #endif
203781180db9Smartijn }
203881180db9Smartijn axo_search.axo_oid.aoi_idlen--;
203981180db9Smartijn } while (axo_search.axo_oid.aoi_idlen > 0);
204081180db9Smartijn axo_search.axo_oid.aoi_idlen = oidlen;
204181180db9Smartijn axo = RB_NFIND(axc_objects, &(axr->axr_axc->axc_objects), &axo_search);
204281180db9Smartijn if (axo != NULL &&
204381180db9Smartijn ax_oid_cmp(&(axo->axo_oid), &(axo_search.axo_oid)) == 2) {
204481180db9Smartijn #ifdef AX_DEBUG
204581180db9Smartijn agentx_log_axc_fatalx(axr->axr_axc, "%s: invalid parent "
204681180db9Smartijn "child object relationship", __func__);
204781180db9Smartijn #else
204881180db9Smartijn agentx_log_axc_warnx(axr->axr_axc, "%s: invalid parent "
204981180db9Smartijn "child object relationship", __func__);
205081180db9Smartijn errno = EINVAL;
205181180db9Smartijn return NULL;
205281180db9Smartijn #endif
205381180db9Smartijn }
205481180db9Smartijn if (implied == 1) {
205533598f3aSmartijn laxi = axi[axilen - 1];
205633598f3aSmartijn if (laxi->axi_vb.avb_type == AX_DATA_TYPE_OCTETSTRING) {
205733598f3aSmartijn if (laxi->axi_vb.avb_data.avb_ostring.aos_slen != 0) {
205881180db9Smartijn #ifdef AX_DEBUG
205981180db9Smartijn agentx_log_axc_fatalx(axr->axr_axc,
206081180db9Smartijn "%s: implied can only be used on strings "
206181180db9Smartijn "of dynamic length", __func__);
206281180db9Smartijn #else
206381180db9Smartijn agentx_log_axc_warnx(axr->axr_axc,
206481180db9Smartijn "%s: implied can only be used on strings "
206581180db9Smartijn "of dynamic length", __func__);
206681180db9Smartijn errno = EINVAL;
206781180db9Smartijn return NULL;
206881180db9Smartijn #endif
206981180db9Smartijn }
207033598f3aSmartijn } else if (laxi->axi_vb.avb_type == AX_DATA_TYPE_OID) {
207133598f3aSmartijn if (laxi->axi_vb.avb_data.avb_oid.aoi_idlen != 0) {
207281180db9Smartijn #ifdef AX_DEBUG
207381180db9Smartijn agentx_log_axc_fatalx(axr->axr_axc,
207481180db9Smartijn "%s: implied can only be used on oids of "
207581180db9Smartijn "dynamic length", __func__);
207681180db9Smartijn #else
207781180db9Smartijn agentx_log_axc_warnx(axr->axr_axc,
207881180db9Smartijn "%s: implied can only be used on oids of "
207981180db9Smartijn "dynamic length", __func__);
208081180db9Smartijn errno = EINVAL;
208181180db9Smartijn return NULL;
208281180db9Smartijn #endif
208381180db9Smartijn }
208481180db9Smartijn } else {
208581180db9Smartijn #ifdef AX_DEBUG
208681180db9Smartijn agentx_log_axc_fatalx(axr->axr_axc, "%s: implied "
208781180db9Smartijn "can only be set on oid and string indices",
208881180db9Smartijn __func__);
208981180db9Smartijn #else
209081180db9Smartijn agentx_log_axc_warnx(axr->axr_axc, "%s: implied can "
209181180db9Smartijn "only be set on oid and string indices", __func__);
209281180db9Smartijn errno = EINVAL;
209381180db9Smartijn return NULL;
209481180db9Smartijn #endif
20959dbe2cd1Smartijn }
20969dbe2cd1Smartijn }
209781180db9Smartijn
209881180db9Smartijn ready = axr->axr_cstate == AX_CSTATE_OPEN;
209981180db9Smartijn if ((axo = calloc(1, sizeof(*axo))) == NULL)
210081180db9Smartijn return NULL;
210181180db9Smartijn axo->axo_axr = axr;
210281180db9Smartijn bcopy(&(axo_search.axo_oid), &(axo->axo_oid), sizeof(axo->axo_oid));
210381180db9Smartijn for (i = 0; i < axilen; i++) {
210481180db9Smartijn axo->axo_index[i] = axi[i];
210581180db9Smartijn if (axi[i]->axi_objectlen == axi[i]->axi_objectsize) {
210633598f3aSmartijn taxo = recallocarray(axi[i]->axi_object,
210781180db9Smartijn axi[i]->axi_objectlen, axi[i]->axi_objectlen + 1,
210881180db9Smartijn sizeof(*axi[i]->axi_object));
210933598f3aSmartijn if (taxo == NULL) {
211081180db9Smartijn free(axo);
211181180db9Smartijn return NULL;
211281180db9Smartijn }
211333598f3aSmartijn axi[i]->axi_object = taxo;
211481180db9Smartijn axi[i]->axi_objectsize = axi[i]->axi_objectlen + 1;
211581180db9Smartijn }
211681180db9Smartijn for (j = 0; j < axi[i]->axi_objectlen; j++) {
211781180db9Smartijn if (ax_oid_cmp(&(axo->axo_oid),
211881180db9Smartijn &(axi[i]->axi_object[j]->axo_oid)) < 0) {
211981180db9Smartijn memmove(&(axi[i]->axi_object[j + 1]),
212081180db9Smartijn &(axi[i]->axi_object[j]),
212181180db9Smartijn sizeof(*(axi[i]->axi_object)) *
212281180db9Smartijn (axi[i]->axi_objectlen - j));
212381180db9Smartijn break;
212481180db9Smartijn }
212581180db9Smartijn }
212681180db9Smartijn axi[i]->axi_object[j] = axo;
212781180db9Smartijn axi[i]->axi_objectlen++;
212881180db9Smartijn if (axi[i]->axi_cstate != AX_CSTATE_OPEN)
212981180db9Smartijn ready = 0;
213081180db9Smartijn }
213181180db9Smartijn axo->axo_indexlen = axilen;
213281180db9Smartijn axo->axo_implied = implied;
213381180db9Smartijn axo->axo_timeout = 0;
213481180db9Smartijn axo->axo_lock = 0;
213581180db9Smartijn axo->axo_get = get;
213681180db9Smartijn axo->axo_cstate = AX_CSTATE_CLOSE;
213781180db9Smartijn axo->axo_dstate = AX_DSTATE_OPEN;
213881180db9Smartijn
213981180db9Smartijn TAILQ_INSERT_TAIL(&(axr->axr_objects), axo, axo_axr_objects);
214081180db9Smartijn RB_INSERT(axc_objects, &(axr->axr_axc->axc_objects), axo);
214181180db9Smartijn
214281180db9Smartijn if (ready)
214381180db9Smartijn agentx_object_start(axo);
214481180db9Smartijn
214581180db9Smartijn return axo;
214681180db9Smartijn }
214781180db9Smartijn
214881180db9Smartijn static int
214981180db9Smartijn agentx_object_start(struct agentx_object *axo)
215081180db9Smartijn {
215181180db9Smartijn struct agentx_region *axr = axo->axo_axr;
215281180db9Smartijn struct agentx_context *axc = axr->axr_axc;
215381180db9Smartijn struct agentx_session *axs = axc->axc_axs;
215481180db9Smartijn struct agentx *ax = axs->axs_ax;
215581180db9Smartijn struct ax_oid oid;
215681180db9Smartijn char oids[1024];
215781180db9Smartijn size_t i;
215881180db9Smartijn int needregister = 0;
215981180db9Smartijn uint32_t packetid;
216081180db9Smartijn uint8_t flags = AX_PDU_FLAG_INSTANCE_REGISTRATION;
216181180db9Smartijn
216281180db9Smartijn #ifdef AX_DEBUG
216381180db9Smartijn if (axr->axr_cstate != AX_CSTATE_OPEN ||
216481180db9Smartijn axo->axo_cstate != AX_CSTATE_CLOSE ||
216581180db9Smartijn axo->axo_dstate != AX_DSTATE_OPEN)
216681180db9Smartijn agentx_log_axc_fatalx(axc,
216781180db9Smartijn "%s: unexpected object registration", __func__);
216881180db9Smartijn #endif
216981180db9Smartijn
217081180db9Smartijn if (axo->axo_timeout != 0)
217181180db9Smartijn needregister = 1;
217281180db9Smartijn for (i = 0; i < axo->axo_indexlen; i++) {
217381180db9Smartijn if (axo->axo_index[i]->axi_cstate != AX_CSTATE_OPEN)
217481180db9Smartijn return 0;
217581180db9Smartijn if (axo->axo_index[i]->axi_type != AXI_TYPE_DYNAMIC)
217681180db9Smartijn needregister = 1;
217781180db9Smartijn }
217881180db9Smartijn if (!needregister) {
217981180db9Smartijn axo->axo_cstate = AX_CSTATE_WAITOPEN;
218081180db9Smartijn agentx_object_finalize(NULL, axo);
21819dbe2cd1Smartijn return 0;
21829dbe2cd1Smartijn }
21839dbe2cd1Smartijn
218481180db9Smartijn bcopy(&(axo->axo_oid), &(oid), sizeof(oid));
218581180db9Smartijn for (i = 0; i < axo->axo_indexlen; i++) {
218681180db9Smartijn if (axo->axo_index[i]->axi_type == AXI_TYPE_DYNAMIC) {
218781180db9Smartijn flags = 0;
218881180db9Smartijn break;
218981180db9Smartijn }
219081180db9Smartijn #ifdef AX_DEBUG
219181180db9Smartijn if (axo->axo_index[i]->axi_vb.avb_type !=
219281180db9Smartijn AX_DATA_TYPE_INTEGER)
219381180db9Smartijn agentx_log_axc_fatalx(axc,
219481180db9Smartijn "%s: Unsupported allocated index type", __func__);
219581180db9Smartijn #endif
219681180db9Smartijn oid.aoi_id[oid.aoi_idlen++] =
21971b6ededeSmartijn axo->axo_index[i]->axi_vb.avb_data.avb_int32;
219881180db9Smartijn }
219981180db9Smartijn packetid = ax_register(ax->ax_ax, flags, axs->axs_id,
220081180db9Smartijn AGENTX_CONTEXT_CTX(axc), axo->axo_timeout,
220181180db9Smartijn AX_PRIORITY_DEFAULT, 0, &oid, 0);
220281180db9Smartijn if (packetid == 0) {
220381180db9Smartijn agentx_log_axc_warn(axc, "couldn't generate %s",
220481180db9Smartijn ax_pdutype2string(AX_PDU_TYPE_REGISTER));
220581180db9Smartijn agentx_reset(ax);
220681180db9Smartijn return -1;
220781180db9Smartijn }
220881180db9Smartijn strlcpy(oids, ax_oid2string(&(axo->axo_oid)), sizeof(oids));
220981180db9Smartijn agentx_log_axc_info(axc, "object %s (%s %s): opening",
221081180db9Smartijn oids, flags ? "instance" : "region", ax_oid2string(&(oid)));
221181180db9Smartijn axo->axo_cstate = AX_CSTATE_WAITOPEN;
221281180db9Smartijn return agentx_request(ax, packetid, agentx_object_finalize, axo);
22139dbe2cd1Smartijn }
22149dbe2cd1Smartijn
221581180db9Smartijn static int
221681180db9Smartijn agentx_object_finalize(struct ax_pdu *pdu, void *cookie)
22179dbe2cd1Smartijn {
221881180db9Smartijn struct agentx_object *axo = cookie;
221981180db9Smartijn struct agentx_context *axc = axo->axo_axr->axr_axc;
222081180db9Smartijn struct ax_oid oid;
222181180db9Smartijn char oids[1024];
222281180db9Smartijn size_t i;
222381180db9Smartijn uint8_t flags = 1;
22249dbe2cd1Smartijn
222581180db9Smartijn #ifdef AX_DEBUG
222681180db9Smartijn if (axo->axo_cstate != AX_CSTATE_WAITOPEN)
222781180db9Smartijn agentx_log_axc_fatalx(axc, "%s: not expecting object open",
222881180db9Smartijn __func__);
222981180db9Smartijn #endif
223081180db9Smartijn
223181180db9Smartijn if (pdu == NULL) {
223281180db9Smartijn axo->axo_cstate = AX_CSTATE_OPEN;
223381180db9Smartijn return 0;
22349dbe2cd1Smartijn }
22359dbe2cd1Smartijn
223681180db9Smartijn bcopy(&(axo->axo_oid), &oid, sizeof(oid));
223781180db9Smartijn for (i = 0; i < axo->axo_indexlen; i++) {
223881180db9Smartijn if (axo->axo_index[i]->axi_type == AXI_TYPE_DYNAMIC) {
223981180db9Smartijn flags = 0;
224081180db9Smartijn break;
224181180db9Smartijn }
224281180db9Smartijn #ifdef AX_DEBUG
224381180db9Smartijn if (axo->axo_index[i]->axi_vb.avb_type !=
224481180db9Smartijn AX_DATA_TYPE_INTEGER)
224581180db9Smartijn agentx_log_axc_fatalx(axc,
224681180db9Smartijn "%s: Unsupported allocated index type", __func__);
224781180db9Smartijn #endif
22489dbe2cd1Smartijn
224981180db9Smartijn oid.aoi_id[oid.aoi_idlen++] =
22501b6ededeSmartijn axo->axo_index[i]->axi_vb.avb_data.avb_int32;
225181180db9Smartijn }
225281180db9Smartijn strlcpy(oids, ax_oid2string(&(axo->axo_oid)), sizeof(oids));
225381180db9Smartijn
225481180db9Smartijn /*
225581180db9Smartijn * We should only be here for table objects with registered indices.
225681180db9Smartijn * If we fail here something is misconfigured and the admin should fix
225781180db9Smartijn * it.
225881180db9Smartijn */
225981180db9Smartijn if (pdu->ap_payload.ap_response.ap_error != AX_PDU_ERROR_NOERROR) {
226081180db9Smartijn axo->axo_cstate = AX_CSTATE_CLOSE;
226181180db9Smartijn agentx_log_axc_info(axc, "object %s (%s %s): %s",
226281180db9Smartijn oids, flags ? "instance" : "region", ax_oid2string(&oid),
226381180db9Smartijn ax_error2string(pdu->ap_payload.ap_response.ap_error));
226481180db9Smartijn return 0;
226581180db9Smartijn }
226681180db9Smartijn axo->axo_cstate = AX_CSTATE_OPEN;
226781180db9Smartijn agentx_log_axc_info(axc, "object %s (%s %s): open", oids,
226881180db9Smartijn flags ? "instance" : "region", ax_oid2string(&oid));
226981180db9Smartijn
227081180db9Smartijn if (axo->axo_dstate == AX_DSTATE_CLOSE)
227181180db9Smartijn return agentx_object_close(axo);
227281180db9Smartijn
227381180db9Smartijn return 0;
22749dbe2cd1Smartijn }
22759dbe2cd1Smartijn
227681180db9Smartijn static int
227781180db9Smartijn agentx_object_lock(struct agentx_object *axo)
227881180db9Smartijn {
227981180db9Smartijn if (axo->axo_lock == UINT32_MAX) {
228081180db9Smartijn agentx_log_axc_warnx(axo->axo_axr->axr_axc,
228181180db9Smartijn "%s: axo_lock == %u", __func__, UINT32_MAX);
228281180db9Smartijn return -1;
228381180db9Smartijn }
228481180db9Smartijn axo->axo_lock++;
228581180db9Smartijn return 0;
228681180db9Smartijn }
228781180db9Smartijn
228881180db9Smartijn static void
228981180db9Smartijn agentx_object_unlock(struct agentx_object *axo)
229081180db9Smartijn {
2291f00a771dSmartijn struct agentx *ax = axo->axo_axr->axr_axc->axc_axs->axs_ax;
2292f00a771dSmartijn
229381180db9Smartijn #ifdef AX_DEBUG
229481180db9Smartijn if (axo->axo_lock == 0)
229581180db9Smartijn agentx_log_axc_fatalx(axo->axo_axr->axr_axc,
229681180db9Smartijn "%s: axo_lock == 0", __func__);
229781180db9Smartijn #endif
229881180db9Smartijn axo->axo_lock--;
2299f00a771dSmartijn if (axo->axo_lock == 0) {
2300f00a771dSmartijn if (!ax->ax_free)
2301f00a771dSmartijn agentx_free_finalize(ax);
2302f00a771dSmartijn }
230381180db9Smartijn }
230481180db9Smartijn
230581180db9Smartijn static int
230681180db9Smartijn agentx_object_close(struct agentx_object *axo)
230781180db9Smartijn {
230881180db9Smartijn struct agentx_context *axc = axo->axo_axr->axr_axc;
230981180db9Smartijn struct agentx_session *axs = axc->axc_axs;
231081180db9Smartijn struct agentx *ax = axs->axs_ax;
231181180db9Smartijn struct ax_oid oid;
231281180db9Smartijn char oids[1024];
231381180db9Smartijn size_t i;
231481180db9Smartijn int needclose = 0;
231581180db9Smartijn uint32_t packetid;
231681180db9Smartijn uint8_t flags = 1;
231781180db9Smartijn
231881180db9Smartijn #ifdef AX_DEBUG
231981180db9Smartijn if (axo->axo_cstate != AX_CSTATE_OPEN)
232081180db9Smartijn agentx_log_axc_fatalx(axc, "%s: unexpected object close",
232181180db9Smartijn __func__);
232281180db9Smartijn #endif
232381180db9Smartijn
232481180db9Smartijn for (i = 0; i < axo->axo_indexlen; i++) {
232581180db9Smartijn #ifdef AX_DEBUG
232681180db9Smartijn if (axo->axo_index[i]->axi_cstate != AX_CSTATE_OPEN)
232781180db9Smartijn agentx_log_axc_fatalx(axc,
232881180db9Smartijn "%s: Object open while index closed", __func__);
232981180db9Smartijn #endif
233081180db9Smartijn if (axo->axo_index[i]->axi_type != AXI_TYPE_DYNAMIC)
233181180db9Smartijn needclose = 1;
233281180db9Smartijn }
233381180db9Smartijn axo->axo_cstate = AX_CSTATE_WAITCLOSE;
233481180db9Smartijn if (axs->axs_cstate == AX_CSTATE_WAITCLOSE)
233581180db9Smartijn return 0;
233681180db9Smartijn if (!needclose) {
233781180db9Smartijn agentx_object_close_finalize(NULL, axo);
233881180db9Smartijn return 0;
233981180db9Smartijn }
234081180db9Smartijn
234181180db9Smartijn bcopy(&(axo->axo_oid), &(oid), sizeof(oid));
234281180db9Smartijn for (i = 0; i < axo->axo_indexlen; i++) {
234381180db9Smartijn if (axo->axo_index[i]->axi_type == AXI_TYPE_DYNAMIC) {
234481180db9Smartijn flags = 0;
234581180db9Smartijn break;
234681180db9Smartijn }
234781180db9Smartijn #ifdef AX_DEBUG
234881180db9Smartijn if (axo->axo_index[i]->axi_vb.avb_type !=
234981180db9Smartijn AX_DATA_TYPE_INTEGER)
235081180db9Smartijn agentx_log_axc_fatalx(axc,
235181180db9Smartijn "%s: Unsupported allocated index type", __func__);
235281180db9Smartijn #endif
235381180db9Smartijn oid.aoi_id[oid.aoi_idlen++] =
23541b6ededeSmartijn axo->axo_index[i]->axi_vb.avb_data.avb_int32;
235581180db9Smartijn }
235681180db9Smartijn packetid = ax_unregister(ax->ax_ax, axs->axs_id,
235781180db9Smartijn AGENTX_CONTEXT_CTX(axc), AX_PRIORITY_DEFAULT, 0, &oid, 0);
235881180db9Smartijn if (packetid == 0) {
235981180db9Smartijn agentx_log_axc_warn(axc, "couldn't generate %s",
236081180db9Smartijn ax_pdutype2string(AX_PDU_TYPE_UNREGISTER));
236181180db9Smartijn agentx_reset(ax);
236281180db9Smartijn return -1;
236381180db9Smartijn }
236481180db9Smartijn strlcpy(oids, ax_oid2string(&(axo->axo_oid)), sizeof(oids));
236581180db9Smartijn agentx_log_axc_info(axc, "object %s (%s %s): closing",
236681180db9Smartijn oids, flags ? "instance" : "region", ax_oid2string(&(oid)));
236781180db9Smartijn return agentx_request(ax, packetid, agentx_object_close_finalize,
236881180db9Smartijn axo);
236981180db9Smartijn }
237081180db9Smartijn
237181180db9Smartijn static int
237281180db9Smartijn agentx_object_close_finalize(struct ax_pdu *pdu, void *cookie)
237381180db9Smartijn {
237481180db9Smartijn struct agentx_object *axo = cookie;
237581180db9Smartijn struct agentx_region *axr = axo->axo_axr;
237681180db9Smartijn struct agentx_context *axc = axr->axr_axc;
237781180db9Smartijn struct agentx_session *axs = axc->axc_axs;
237881180db9Smartijn struct agentx *ax = axs->axs_ax;
237981180db9Smartijn struct ax_oid oid;
238081180db9Smartijn char oids[1024];
238181180db9Smartijn uint8_t flags = 1;
238281180db9Smartijn size_t i;
2383f00a771dSmartijn int axfree = ax->ax_free;
238481180db9Smartijn
238581180db9Smartijn #ifdef AX_DEBUG
238681180db9Smartijn if (axo->axo_cstate != AX_CSTATE_WAITCLOSE)
238781180db9Smartijn agentx_log_axc_fatalx(axc,
238881180db9Smartijn "%s: unexpected object unregister", __func__);
238981180db9Smartijn #endif
239081180db9Smartijn
239181180db9Smartijn if (pdu != NULL) {
239281180db9Smartijn bcopy(&(axo->axo_oid), &(oid), sizeof(oid));
239381180db9Smartijn for (i = 0; i < axo->axo_indexlen; i++) {
239481180db9Smartijn if (axo->axo_index[i]->axi_type == AXI_TYPE_DYNAMIC) {
239581180db9Smartijn flags = 0;
239681180db9Smartijn break;
239781180db9Smartijn }
239881180db9Smartijn #ifdef AX_DEBUG
239981180db9Smartijn if (axo->axo_index[i]->axi_vb.avb_type !=
240081180db9Smartijn AX_DATA_TYPE_INTEGER)
240181180db9Smartijn agentx_log_axc_fatalx(axc,
240281180db9Smartijn "%s: Unsupported allocated index type",
240381180db9Smartijn __func__);
240481180db9Smartijn #endif
240581180db9Smartijn oid.aoi_id[oid.aoi_idlen++] =
24061b6ededeSmartijn axo->axo_index[i]->axi_vb.avb_data.avb_int32;
240781180db9Smartijn }
240881180db9Smartijn strlcpy(oids, ax_oid2string(&(axo->axo_oid)), sizeof(oids));
240981180db9Smartijn if (pdu->ap_payload.ap_response.ap_error !=
241081180db9Smartijn AX_PDU_ERROR_NOERROR) {
241181180db9Smartijn agentx_log_axc_warnx(axc,
241281180db9Smartijn "closing object %s (%s %s): %s", oids,
241381180db9Smartijn flags ? "instance" : "region",
241481180db9Smartijn ax_oid2string(&oid), ax_error2string(
241581180db9Smartijn pdu->ap_payload.ap_response.ap_error));
241681180db9Smartijn agentx_reset(ax);
241781180db9Smartijn return -1;
241881180db9Smartijn }
241981180db9Smartijn agentx_log_axc_info(axc, "object %s (%s %s): closed", oids,
242081180db9Smartijn flags ? "instance" : "region", ax_oid2string(&oid));
242181180db9Smartijn }
242281180db9Smartijn
2423f00a771dSmartijn ax->ax_free = 1;
2424f00a771dSmartijn if (axr->axr_cstate == AX_CSTATE_OPEN &&
2425f00a771dSmartijn axo->axo_dstate == AX_DSTATE_OPEN)
2426f00a771dSmartijn agentx_object_start(axo);
2427f00a771dSmartijn
2428f00a771dSmartijn if (!axfree)
2429f00a771dSmartijn agentx_free_finalize(ax);
243081180db9Smartijn
243181180db9Smartijn return 0;
243281180db9Smartijn }
243381180db9Smartijn
243481180db9Smartijn void
243581180db9Smartijn agentx_object_free(struct agentx_object *axo)
243681180db9Smartijn {
2437f00a771dSmartijn struct agentx *ax;
2438f00a771dSmartijn int axfree;
2439f00a771dSmartijn
244081180db9Smartijn if (axo == NULL)
244181180db9Smartijn return;
244281180db9Smartijn
2443f00a771dSmartijn ax = axo->axo_axr->axr_axc->axc_axs->axs_ax;
2444f00a771dSmartijn axfree = ax->ax_free;
2445f00a771dSmartijn ax->ax_free = 1;
2446f00a771dSmartijn
244781180db9Smartijn if (axo->axo_dstate == AX_DSTATE_CLOSE)
244881180db9Smartijn agentx_log_axc_fatalx(axo->axo_axr->axr_axc,
244981180db9Smartijn "%s: double free", __func__);
245081180db9Smartijn
245181180db9Smartijn axo->axo_dstate = AX_DSTATE_CLOSE;
245281180db9Smartijn
2453f00a771dSmartijn if (axo->axo_cstate == AX_CSTATE_OPEN)
2454f00a771dSmartijn agentx_object_close(axo);
2455f00a771dSmartijn if (!axfree)
2456f00a771dSmartijn agentx_free_finalize(ax);
245781180db9Smartijn }
245881180db9Smartijn
245981180db9Smartijn static void
246081180db9Smartijn agentx_object_free_finalize(struct agentx_object *axo)
246181180db9Smartijn {
246281180db9Smartijn #ifdef AX_DEBUG
246381180db9Smartijn struct agentx *ax = axo->axo_axr->axr_axc->axc_axs->axs_ax;
246481180db9Smartijn #endif
246581180db9Smartijn size_t i, j;
246681180db9Smartijn int found;
246781180db9Smartijn
2468f00a771dSmartijn if (axo->axo_dstate != AX_DSTATE_CLOSE ||
2469f00a771dSmartijn axo->axo_cstate != AX_CSTATE_CLOSE ||
2470f00a771dSmartijn axo->axo_lock != 0)
247181180db9Smartijn return;
247281180db9Smartijn
247381180db9Smartijn RB_REMOVE(axc_objects, &(axo->axo_axr->axr_axc->axc_objects), axo);
247481180db9Smartijn TAILQ_REMOVE(&(axo->axo_axr->axr_objects), axo, axo_axr_objects);
247581180db9Smartijn
247681180db9Smartijn for (i = 0; i < axo->axo_indexlen; i++) {
247781180db9Smartijn found = 0;
247881180db9Smartijn for (j = 0; j < axo->axo_index[i]->axi_objectlen; j++) {
247981180db9Smartijn if (axo->axo_index[i]->axi_object[j] == axo)
248081180db9Smartijn found = 1;
248181180db9Smartijn if (found && j + 1 != axo->axo_index[i]->axi_objectlen)
248281180db9Smartijn axo->axo_index[i]->axi_object[j] =
248381180db9Smartijn axo->axo_index[i]->axi_object[j + 1];
248481180db9Smartijn }
248581180db9Smartijn #ifdef AX_DEBUG
248681180db9Smartijn if (!found)
248781180db9Smartijn agentx_log_axc_fatalx(axo->axo_axr->axr_axc,
248881180db9Smartijn "%s: object not found in index", __func__);
248981180db9Smartijn #endif
249081180db9Smartijn axo->axo_index[i]->axi_objectlen--;
249181180db9Smartijn }
249281180db9Smartijn
249381180db9Smartijn free(axo);
249481180db9Smartijn }
249581180db9Smartijn
249681180db9Smartijn static void
249781180db9Smartijn agentx_object_reset(struct agentx_object *axo)
249881180db9Smartijn {
2499f00a771dSmartijn struct agentx *ax = axo->axo_axr->axr_axc->axc_axs->axs_ax;
2500f00a771dSmartijn
250181180db9Smartijn axo->axo_cstate = AX_CSTATE_CLOSE;
250281180db9Smartijn
2503f00a771dSmartijn if (!ax->ax_free)
2504f00a771dSmartijn agentx_free_finalize(ax);
250581180db9Smartijn }
250681180db9Smartijn
250781180db9Smartijn static int
250881180db9Smartijn agentx_object_cmp(struct agentx_object *o1, struct agentx_object *o2)
250981180db9Smartijn {
251081180db9Smartijn return ax_oid_cmp(&(o1->axo_oid), &(o2->axo_oid));
251181180db9Smartijn }
251281180db9Smartijn
251381180db9Smartijn static int
251481180db9Smartijn agentx_object_implied(struct agentx_object *axo,
251581180db9Smartijn struct agentx_index *axi)
25169dbe2cd1Smartijn {
25179dbe2cd1Smartijn size_t i = 0;
2518af021b53Smartijn struct ax_varbind *vb;
25199dbe2cd1Smartijn
252081180db9Smartijn for (i = 0; i < axo->axo_indexlen; i++) {
252181180db9Smartijn if (axo->axo_index[i] == axi) {
2522af021b53Smartijn vb = &axi->axi_vb;
2523af021b53Smartijn if (vb->avb_type == AX_DATA_TYPE_OCTETSTRING &&
2524af021b53Smartijn vb->avb_data.avb_ostring.aos_slen != 0)
2525af021b53Smartijn return 1;
2526af021b53Smartijn else if (vb->avb_type == AX_DATA_TYPE_OID &&
2527af021b53Smartijn vb->avb_data.avb_oid.aoi_idlen != 0)
252881180db9Smartijn return 1;
252981180db9Smartijn else if (i == axo->axo_indexlen - 1)
253081180db9Smartijn return axo->axo_implied;
25319dbe2cd1Smartijn return 0;
25329dbe2cd1Smartijn }
253381180db9Smartijn }
253481180db9Smartijn #ifdef AX_DEBUG
253581180db9Smartijn agentx_log_axc_fatalx(axo->axo_axr->axr_axc, "%s: unsupported index",
253681180db9Smartijn __func__);
253781180db9Smartijn #endif
253881180db9Smartijn return 0;
253981180db9Smartijn }
254081180db9Smartijn
254181180db9Smartijn static void
254281180db9Smartijn agentx_get_start(struct agentx_context *axc, struct ax_pdu *pdu)
254381180db9Smartijn {
254481180db9Smartijn struct agentx_session *axs = axc->axc_axs;
254581180db9Smartijn struct agentx *ax = axs->axs_ax;
254633598f3aSmartijn struct agentx_get *axg, taxg;
254781180db9Smartijn struct ax_pdu_searchrangelist *srl;
254881180db9Smartijn char *logmsg = NULL;
254981180db9Smartijn size_t i, j;
255081180db9Smartijn int fail = 0;
255181180db9Smartijn
255281180db9Smartijn if ((axg = calloc(1, sizeof(*axg))) == NULL) {
255333598f3aSmartijn taxg.axg_sessionid = pdu->ap_header.aph_sessionid;
255433598f3aSmartijn taxg.axg_transactionid = pdu->ap_header.aph_transactionid;
255533598f3aSmartijn taxg.axg_packetid = pdu->ap_header.aph_packetid;
255633598f3aSmartijn taxg.axg_context_default = axc->axc_name_default;
255733598f3aSmartijn taxg.axg_fd = axc->axc_axs->axs_ax->ax_fd;
255833598f3aSmartijn agentx_log_axg_warn(&taxg, "Couldn't parse request");
255981180db9Smartijn agentx_reset(ax);
256081180db9Smartijn return;
256181180db9Smartijn }
256281180db9Smartijn
256381180db9Smartijn axg->axg_sessionid = pdu->ap_header.aph_sessionid;
256481180db9Smartijn axg->axg_transactionid = pdu->ap_header.aph_transactionid;
256581180db9Smartijn axg->axg_packetid = pdu->ap_header.aph_packetid;
256681180db9Smartijn axg->axg_context_default = axc->axc_name_default;
256781180db9Smartijn axg->axg_fd = axc->axc_axs->axs_ax->ax_fd;
256881180db9Smartijn if (!axc->axc_name_default) {
256981180db9Smartijn axg->axg_context.aos_string =
257081180db9Smartijn (unsigned char *)strdup((char *)axc->axc_name.aos_string);
257181180db9Smartijn if (axg->axg_context.aos_string == NULL) {
257281180db9Smartijn agentx_log_axg_warn(axg, "Couldn't parse request");
257381180db9Smartijn free(axg);
257481180db9Smartijn agentx_reset(ax);
257581180db9Smartijn return;
257681180db9Smartijn }
257781180db9Smartijn }
257881180db9Smartijn axg->axg_context.aos_slen = axc->axc_name.aos_slen;
257981180db9Smartijn axg->axg_type = pdu->ap_header.aph_type;
258081180db9Smartijn axg->axg_axc = axc;
258181180db9Smartijn TAILQ_INSERT_TAIL(&(ax->ax_getreqs), axg, axg_ax_getreqs);
258281180db9Smartijn if (axg->axg_type == AX_PDU_TYPE_GET ||
258381180db9Smartijn axg->axg_type == AX_PDU_TYPE_GETNEXT) {
258481180db9Smartijn srl = &(pdu->ap_payload.ap_srl);
258581180db9Smartijn axg->axg_nvarbind = srl->ap_nsr;
258681180db9Smartijn } else {
258781180db9Smartijn axg->axg_nonrep = pdu->ap_payload.ap_getbulk.ap_nonrep;
258881180db9Smartijn axg->axg_maxrep = pdu->ap_payload.ap_getbulk.ap_maxrep;
258981180db9Smartijn srl = &(pdu->ap_payload.ap_getbulk.ap_srl);
259081180db9Smartijn axg->axg_nvarbind = ((srl->ap_nsr - axg->axg_nonrep) *
259181180db9Smartijn axg->axg_maxrep) + axg->axg_nonrep;
259281180db9Smartijn }
259381180db9Smartijn
259481180db9Smartijn if ((axg->axg_varbind = calloc(axg->axg_nvarbind,
259581180db9Smartijn sizeof(*(axg->axg_varbind)))) == NULL) {
259681180db9Smartijn agentx_log_axg_warn(axg, "Couldn't parse request");
259781180db9Smartijn agentx_get_free(axg);
259881180db9Smartijn agentx_reset(ax);
259981180db9Smartijn return;
260081180db9Smartijn }
260181180db9Smartijn
260281180db9Smartijn /* XXX net-snmp doesn't use getbulk, so untested */
260381180db9Smartijn /* Two loops: varbind after needs to be initialized */
260481180db9Smartijn for (i = 0; i < srl->ap_nsr; i++) {
260581180db9Smartijn if (i < axg->axg_nonrep ||
260681180db9Smartijn axg->axg_type != AX_PDU_TYPE_GETBULK)
260781180db9Smartijn j = i;
260881180db9Smartijn else if (axg->axg_maxrep == 0)
260981180db9Smartijn break;
261081180db9Smartijn else
261181180db9Smartijn j = (axg->axg_maxrep * i) + axg->axg_nonrep;
261281180db9Smartijn bcopy(&(srl->ap_sr[i].asr_start),
261381180db9Smartijn &(axg->axg_varbind[j].axv_vb.avb_oid),
261481180db9Smartijn sizeof(srl->ap_sr[i].asr_start));
261581180db9Smartijn bcopy(&(srl->ap_sr[i].asr_start),
261681180db9Smartijn &(axg->axg_varbind[j].axv_start),
261781180db9Smartijn sizeof(srl->ap_sr[i].asr_start));
261881180db9Smartijn bcopy(&(srl->ap_sr[i].asr_stop),
261981180db9Smartijn &(axg->axg_varbind[j].axv_end),
262081180db9Smartijn sizeof(srl->ap_sr[i].asr_stop));
262181180db9Smartijn axg->axg_varbind[j].axv_initialized = 1;
262281180db9Smartijn axg->axg_varbind[j].axv_axg = axg;
262381180db9Smartijn axg->axg_varbind[j].axv_include =
262481180db9Smartijn srl->ap_sr[i].asr_start.aoi_include;
262581180db9Smartijn if (j == 0)
262681180db9Smartijn fail |= agentx_strcat(&logmsg, " {");
262781180db9Smartijn else
262881180db9Smartijn fail |= agentx_strcat(&logmsg, ",{");
262981180db9Smartijn fail |= agentx_strcat(&logmsg,
263081180db9Smartijn ax_oid2string(&(srl->ap_sr[i].asr_start)));
263181180db9Smartijn if (srl->ap_sr[i].asr_start.aoi_include)
263281180db9Smartijn fail |= agentx_strcat(&logmsg, " (inclusive)");
263381180db9Smartijn if (srl->ap_sr[i].asr_stop.aoi_idlen != 0) {
263481180db9Smartijn fail |= agentx_strcat(&logmsg, " - ");
263581180db9Smartijn fail |= agentx_strcat(&logmsg,
263681180db9Smartijn ax_oid2string(&(srl->ap_sr[i].asr_stop)));
263781180db9Smartijn }
263881180db9Smartijn fail |= agentx_strcat(&logmsg, "}");
263981180db9Smartijn if (fail) {
264081180db9Smartijn agentx_log_axg_warn(axg, "Couldn't parse request");
264181180db9Smartijn free(logmsg);
264281180db9Smartijn agentx_get_free(axg);
264381180db9Smartijn agentx_reset(ax);
264481180db9Smartijn return;
264581180db9Smartijn }
264681180db9Smartijn }
264781180db9Smartijn
264881180db9Smartijn agentx_log_axg_debug(axg, "%s:%s",
264981180db9Smartijn ax_pdutype2string(axg->axg_type), logmsg);
265081180db9Smartijn free(logmsg);
265181180db9Smartijn
265281180db9Smartijn for (i = 0; i < srl->ap_nsr; i++) {
265381180db9Smartijn if (i < axg->axg_nonrep ||
265481180db9Smartijn axg->axg_type != AX_PDU_TYPE_GETBULK)
265581180db9Smartijn j = i;
265681180db9Smartijn else if (axg->axg_maxrep == 0)
265781180db9Smartijn break;
265881180db9Smartijn else
265981180db9Smartijn j = (axg->axg_maxrep * i) + axg->axg_nonrep;
266081180db9Smartijn agentx_varbind_start(&(axg->axg_varbind[j]));
266181180db9Smartijn }
266281180db9Smartijn }
266381180db9Smartijn
266481180db9Smartijn static void
266581180db9Smartijn agentx_get_finalize(struct agentx_get *axg)
266681180db9Smartijn {
266781180db9Smartijn struct agentx_context *axc = axg->axg_axc;
266856d20486Smartijn struct agentx_session *axs;
266956d20486Smartijn struct agentx *ax;
267081180db9Smartijn size_t i, j, nvarbind = 0;
267181180db9Smartijn uint16_t error = 0, index = 0;
267281180db9Smartijn struct ax_varbind *vbl;
267381180db9Smartijn char *logmsg = NULL;
267481180db9Smartijn int fail = 0;
267581180db9Smartijn
267681180db9Smartijn for (i = 0; i < axg->axg_nvarbind; i++) {
267781180db9Smartijn if (axg->axg_varbind[i].axv_initialized) {
267881180db9Smartijn if (axg->axg_varbind[i].axv_vb.avb_type == 0)
267981180db9Smartijn return;
268081180db9Smartijn nvarbind++;
268181180db9Smartijn }
268281180db9Smartijn }
268381180db9Smartijn
268456d20486Smartijn if (axc == NULL) {
268581180db9Smartijn agentx_get_free(axg);
268681180db9Smartijn return;
268781180db9Smartijn }
268881180db9Smartijn
268956d20486Smartijn axs = axc->axc_axs;
269056d20486Smartijn ax = axs->axs_ax;
269156d20486Smartijn
269281180db9Smartijn if ((vbl = calloc(nvarbind, sizeof(*vbl))) == NULL) {
269381180db9Smartijn agentx_log_axg_warn(axg, "Couldn't parse request");
269481180db9Smartijn agentx_get_free(axg);
269581180db9Smartijn agentx_reset(ax);
269681180db9Smartijn return;
269781180db9Smartijn }
269881180db9Smartijn for (i = 0, j = 0; i < axg->axg_nvarbind; i++) {
269981180db9Smartijn if (axg->axg_varbind[i].axv_initialized) {
270081180db9Smartijn memcpy(&(vbl[j]), &(axg->axg_varbind[i].axv_vb),
270181180db9Smartijn sizeof(*vbl));
270281180db9Smartijn if (error == 0 && axg->axg_varbind[i].axv_error !=
270381180db9Smartijn AX_PDU_ERROR_NOERROR) {
270481180db9Smartijn error = axg->axg_varbind[i].axv_error;
270581180db9Smartijn index = j + 1;
270681180db9Smartijn }
270781180db9Smartijn if (j == 0)
270881180db9Smartijn fail |= agentx_strcat(&logmsg, " {");
270981180db9Smartijn else
271081180db9Smartijn fail |= agentx_strcat(&logmsg, ",{");
271181180db9Smartijn fail |= agentx_strcat(&logmsg,
271281180db9Smartijn ax_varbind2string(&(vbl[j])));
271381180db9Smartijn if (axg->axg_varbind[i].axv_error !=
271481180db9Smartijn AX_PDU_ERROR_NOERROR) {
271581180db9Smartijn fail |= agentx_strcat(&logmsg, "(");
271681180db9Smartijn fail |= agentx_strcat(&logmsg,
271781180db9Smartijn ax_error2string(
271881180db9Smartijn axg->axg_varbind[i].axv_error));
271981180db9Smartijn fail |= agentx_strcat(&logmsg, ")");
272081180db9Smartijn }
272181180db9Smartijn fail |= agentx_strcat(&logmsg, "}");
272281180db9Smartijn if (fail) {
272381180db9Smartijn agentx_log_axg_warn(axg,
272481180db9Smartijn "Couldn't parse request");
272581180db9Smartijn free(logmsg);
272681180db9Smartijn agentx_get_free(axg);
272781180db9Smartijn return;
272881180db9Smartijn }
272981180db9Smartijn j++;
273081180db9Smartijn }
273181180db9Smartijn }
273281180db9Smartijn agentx_log_axg_debug(axg, "response:%s", logmsg);
273381180db9Smartijn free(logmsg);
273481180db9Smartijn
273581180db9Smartijn if (ax_response(ax->ax_ax, axs->axs_id, axg->axg_transactionid,
27366f5d9364Smartijn axg->axg_packetid, 0, error, index, vbl, nvarbind) == -1) {
273781180db9Smartijn agentx_log_axg_warn(axg, "Couldn't parse request");
273881180db9Smartijn agentx_reset(ax);
273981180db9Smartijn } else
274081180db9Smartijn agentx_wantwrite(ax, ax->ax_fd);
274181180db9Smartijn free(vbl);
274281180db9Smartijn agentx_get_free(axg);
274381180db9Smartijn }
274481180db9Smartijn
274581180db9Smartijn void
274681180db9Smartijn agentx_get_free(struct agentx_get *axg)
274781180db9Smartijn {
274881180db9Smartijn struct agentx_varbind *axv;
274981180db9Smartijn struct agentx_object *axo;
275056d20486Smartijn struct agentx *ax;
275181180db9Smartijn struct agentx_varbind_index *index;
275281180db9Smartijn size_t i, j;
275381180db9Smartijn
275456d20486Smartijn if (axg->axg_axc != NULL) {
275556d20486Smartijn ax = axg->axg_axc->axc_axs->axs_ax;
275681180db9Smartijn TAILQ_REMOVE(&(ax->ax_getreqs), axg, axg_ax_getreqs);
275756d20486Smartijn }
275881180db9Smartijn
275981180db9Smartijn for (i = 0; i < axg->axg_nvarbind; i++) {
276081180db9Smartijn axv = &(axg->axg_varbind[i]);
276181180db9Smartijn for (j = 0; axv->axv_axo != NULL &&
276281180db9Smartijn j < axv->axv_axo->axo_indexlen; j++) {
276381180db9Smartijn axo = axv->axv_axo;
276481180db9Smartijn index = &(axv->axv_index[j]);
276581180db9Smartijn if (axo->axo_index[j]->axi_vb.avb_type ==
276681180db9Smartijn AX_DATA_TYPE_OCTETSTRING ||
276781180db9Smartijn axo->axo_index[j]->axi_vb.avb_type ==
276881180db9Smartijn AX_DATA_TYPE_IPADDRESS)
276981180db9Smartijn free(index->axv_idata.avb_ostring.aos_string);
277081180db9Smartijn }
277181180db9Smartijn ax_varbind_free(&(axg->axg_varbind[i].axv_vb));
277281180db9Smartijn }
277381180db9Smartijn
277481180db9Smartijn free(axg->axg_context.aos_string);
277581180db9Smartijn free(axg->axg_varbind);
277681180db9Smartijn free(axg);
277781180db9Smartijn }
277881180db9Smartijn
277981180db9Smartijn static void
278081180db9Smartijn agentx_varbind_start(struct agentx_varbind *axv)
278181180db9Smartijn {
278281180db9Smartijn struct agentx_get *axg = axv->axv_axg;
278381180db9Smartijn struct agentx_context *axc = axg->axg_axc;
278481180db9Smartijn struct agentx_object *axo, axo_search;
278581180db9Smartijn struct agentx_varbind_index *index;
278681180db9Smartijn struct ax_oid *oid;
278781180db9Smartijn union ax_data *data;
278881180db9Smartijn struct in_addr *ipaddress;
278981180db9Smartijn unsigned char *ipbytes;
279081180db9Smartijn size_t i, j, k;
279181180db9Smartijn int overflow = 0, dynamic;
279281180db9Smartijn
279381180db9Smartijn #ifdef AX_DEBUG
279481180db9Smartijn if (!axv->axv_initialized)
279581180db9Smartijn agentx_log_axg_fatalx(axv->axv_axg,
279681180db9Smartijn "%s: axv_initialized not set", __func__);
279781180db9Smartijn #endif
279881180db9Smartijn
279956d20486Smartijn if (axc == NULL) {
280056d20486Smartijn agentx_varbind_error_type(axv, AX_PDU_ERROR_PROCESSINGERROR, 1);
280156d20486Smartijn return;
280256d20486Smartijn }
280356d20486Smartijn
280481180db9Smartijn bcopy(&(axv->axv_vb.avb_oid), &(axo_search.axo_oid),
280581180db9Smartijn sizeof(axo_search.axo_oid));
280681180db9Smartijn
280781180db9Smartijn do {
280881180db9Smartijn axo = RB_FIND(axc_objects, &(axc->axc_objects), &axo_search);
280981180db9Smartijn if (axo_search.axo_oid.aoi_idlen > 0)
281081180db9Smartijn axo_search.axo_oid.aoi_idlen--;
281181180db9Smartijn } while (axo == NULL && axo_search.axo_oid.aoi_idlen > 0);
281281180db9Smartijn if (axo == NULL || axo->axo_cstate != AX_CSTATE_OPEN) {
281381180db9Smartijn axv->axv_include = 1;
281481180db9Smartijn if (axv->axv_axg->axg_type == AX_PDU_TYPE_GET) {
281581180db9Smartijn agentx_varbind_nosuchobject(axv);
281681180db9Smartijn return;
281781180db9Smartijn }
281881180db9Smartijn bcopy(&(axv->axv_vb.avb_oid), &(axo_search.axo_oid),
281981180db9Smartijn sizeof(axo_search.axo_oid));
282081180db9Smartijn axo = RB_NFIND(axc_objects, &(axc->axc_objects), &axo_search);
282181180db9Smartijn getnext:
282281180db9Smartijn while (axo != NULL && axo->axo_cstate != AX_CSTATE_OPEN)
282381180db9Smartijn axo = RB_NEXT(axc_objects, &(axc->axc_objects), axo);
2824fd375ddbSmartijn if (axo == NULL ||
2825*c5fcbd5aSmartijn ax_oid_cmp(&(axo->axo_oid), &(axv->axv_end)) >= 0) {
282681180db9Smartijn agentx_varbind_endofmibview(axv);
282781180db9Smartijn return;
282881180db9Smartijn }
282981180db9Smartijn bcopy(&(axo->axo_oid), &(axv->axv_vb.avb_oid),
283081180db9Smartijn sizeof(axo->axo_oid));
283181180db9Smartijn }
283281180db9Smartijn axv->axv_axo = axo;
283381180db9Smartijn axv->axv_indexlen = axo->axo_indexlen;
283481180db9Smartijn if (agentx_object_lock(axo) == -1) {
283581180db9Smartijn agentx_varbind_error_type(axv,
283681180db9Smartijn AX_PDU_ERROR_PROCESSINGERROR, 1);
283781180db9Smartijn return;
283881180db9Smartijn }
283981180db9Smartijn
284081180db9Smartijn oid = &(axv->axv_vb.avb_oid);
284181180db9Smartijn if (axo->axo_indexlen == 0) {
284281180db9Smartijn if (axv->axv_axg->axg_type == AX_PDU_TYPE_GET) {
284381180db9Smartijn if (oid->aoi_idlen != axo->axo_oid.aoi_idlen + 1 ||
284481180db9Smartijn oid->aoi_id[oid->aoi_idlen - 1] != 0) {
284581180db9Smartijn agentx_varbind_nosuchinstance(axv);
284681180db9Smartijn return;
284781180db9Smartijn }
284881180db9Smartijn } else {
284981180db9Smartijn if (oid->aoi_idlen == axo->axo_oid.aoi_idlen) {
285081180db9Smartijn oid->aoi_id[oid->aoi_idlen++] = 0;
285181180db9Smartijn axv->axv_include = 1;
285281180db9Smartijn } else {
285381180db9Smartijn axv->axv_axo = NULL;
285481180db9Smartijn agentx_object_unlock(axo);
285581180db9Smartijn axo = RB_NEXT(axc_objects, &(axc->axc_objects),
285681180db9Smartijn axo);
285781180db9Smartijn goto getnext;
285881180db9Smartijn }
285981180db9Smartijn }
28600f9df26dSmartijn j = oid->aoi_idlen;
28610f9df26dSmartijn } else
286281180db9Smartijn j = axo->axo_oid.aoi_idlen;
286381180db9Smartijn /*
286481180db9Smartijn * We can't trust what the client gives us, so sometimes we need to map it to
286581180db9Smartijn * index type.
286681180db9Smartijn * - AX_PDU_TYPE_GET: we always return AX_DATA_TYPE_NOSUCHINSTANCE
286781180db9Smartijn * - AX_PDU_TYPE_GETNEXT:
28680f9df26dSmartijn * - Missing OID digits to match indices or !dynamic indices
28692c53affbSjmc * (AX_DATA_TYPE_INTEGER) underflows will result in the following indices to
28700f9df26dSmartijn * be NUL-initialized and the request type will be set to
287181180db9Smartijn * AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE
287281180db9Smartijn * - An overflow can happen on AX_DATA_TYPE_OCTETSTRING and
28730f9df26dSmartijn * AX_DATA_TYPE_IPADDRESS data, and AX_DATA_TYPE_OCTETSTRING and
28740f9df26dSmartijn * AX_DATA_TYPE_OID length. This results in request type being set to
287581180db9Smartijn * AGENTX_REQUEST_TYPE_GETNEXT and will set the index to its maximum
287681180db9Smartijn * value:
287781180db9Smartijn * - AX_DATA_TYPE_INTEGER: UINT32_MAX
287881180db9Smartijn * - AX_DATA_TYPE_OCTETSTRING: aos_slen = UINT32_MAX and
287981180db9Smartijn * aos_string = NULL
288081180db9Smartijn * - AX_DATA_TYPE_OID: aoi_idlen = UINT32_MAX and aoi_id[x] = UINT32_MAX
288181180db9Smartijn * - AX_DATA_TYPE_IPADDRESS: 255.255.255.255
288281180db9Smartijn */
28830f9df26dSmartijn for (dynamic = 0, i = 0; i < axo->axo_indexlen; i++, j++) {
288481180db9Smartijn index = &(axv->axv_index[i]);
288581180db9Smartijn index->axv_axi = axo->axo_index[i];
288681180db9Smartijn data = &(index->axv_idata);
288781180db9Smartijn if (axo->axo_index[i]->axi_type == AXI_TYPE_DYNAMIC)
288881180db9Smartijn dynamic = 1;
288981180db9Smartijn switch (axo->axo_index[i]->axi_vb.avb_type) {
289081180db9Smartijn case AX_DATA_TYPE_INTEGER:
28910f9df26dSmartijn if (index->axv_axi->axi_type != AXI_TYPE_DYNAMIC) {
28920f9df26dSmartijn index->axv_idata.avb_int32 =
28930f9df26dSmartijn index->axv_axi->axi_vb.avb_data.avb_int32;
28940f9df26dSmartijn if (overflow == 0) {
28950f9df26dSmartijn if ((uint32_t)index->axv_idata.avb_int32 >
28960f9df26dSmartijn oid->aoi_id[j])
28970f9df26dSmartijn overflow = -1;
28980f9df26dSmartijn else if ((uint32_t)index->axv_idata.avb_int32 <
28990f9df26dSmartijn oid->aoi_id[j])
29001b6ededeSmartijn overflow = 1;
290181180db9Smartijn }
29020f9df26dSmartijn } else if (overflow == 1)
29030f9df26dSmartijn index->axv_idata.avb_int32 = INT32_MAX;
29040f9df26dSmartijn else if (j >= oid->aoi_idlen || overflow == -1)
29050f9df26dSmartijn index->axv_idata.avb_int32 = 0;
29060f9df26dSmartijn else {
29070f9df26dSmartijn if (oid->aoi_id[j] > INT32_MAX) {
29080f9df26dSmartijn index->axv_idata.avb_int32 = INT32_MAX;
290981180db9Smartijn overflow = 1;
29100f9df26dSmartijn } else
29110f9df26dSmartijn index->axv_idata.avb_int32 =
29120f9df26dSmartijn oid->aoi_id[j];
291381180db9Smartijn }
291481180db9Smartijn break;
291581180db9Smartijn case AX_DATA_TYPE_OCTETSTRING:
29160f9df26dSmartijn if (overflow == 1) {
29170f9df26dSmartijn data->avb_ostring.aos_slen = UINT32_MAX;
29180f9df26dSmartijn data->avb_ostring.aos_string = NULL;
29190f9df26dSmartijn continue;
29200f9df26dSmartijn } else if (j >= oid->aoi_idlen || overflow == -1) {
29210f9df26dSmartijn data->avb_ostring.aos_slen = 0;
29220f9df26dSmartijn data->avb_ostring.aos_string = NULL;
29230f9df26dSmartijn continue;
29240f9df26dSmartijn }
29250f9df26dSmartijn if (agentx_object_implied(axo, index->axv_axi))
29260f9df26dSmartijn data->avb_ostring.aos_slen = oid->aoi_idlen - j;
29270f9df26dSmartijn else {
29280f9df26dSmartijn data->avb_ostring.aos_slen = oid->aoi_id[j++];
29290f9df26dSmartijn if (data->avb_ostring.aos_slen >=
29300f9df26dSmartijn AGENTX_OID_MAX_LEN - j) {
29310f9df26dSmartijn data->avb_ostring.aos_slen = UINT32_MAX;
293281180db9Smartijn overflow = 1;
293381180db9Smartijn }
293481180db9Smartijn }
29350f9df26dSmartijn if (data->avb_ostring.aos_slen == UINT32_MAX ||
29360f9df26dSmartijn data->avb_ostring.aos_slen == 0) {
29370f9df26dSmartijn data->avb_ostring.aos_string = NULL;
29380f9df26dSmartijn continue;
293981180db9Smartijn }
294081180db9Smartijn data->avb_ostring.aos_string =
29410f9df26dSmartijn malloc(data->avb_ostring.aos_slen + 1);
294281180db9Smartijn if (data->avb_ostring.aos_string == NULL) {
294381180db9Smartijn agentx_log_axg_warn(axg,
294481180db9Smartijn "Failed to bind string index");
294581180db9Smartijn agentx_varbind_error_type(axv,
294681180db9Smartijn AX_PDU_ERROR_PROCESSINGERROR, 1);
294781180db9Smartijn return;
294881180db9Smartijn }
294981180db9Smartijn for (k = 0; k < data->avb_ostring.aos_slen; k++, j++) {
29500f9df26dSmartijn if (j < oid->aoi_idlen && oid->aoi_id[j] > 0xff)
295181180db9Smartijn overflow = 1;
29520f9df26dSmartijn if (overflow == 1)
29530f9df26dSmartijn data->avb_ostring.aos_string[k] = 0xff;
29540f9df26dSmartijn else if (j >= oid->aoi_idlen || overflow == -1)
29550f9df26dSmartijn data->avb_ostring.aos_string[k] = '\0';
29560f9df26dSmartijn else
29570f9df26dSmartijn data->avb_ostring.aos_string[k] =
29580f9df26dSmartijn oid->aoi_id[j];
295981180db9Smartijn }
29600f9df26dSmartijn data->avb_ostring.aos_string[k] = '\0';
29610f9df26dSmartijn j--;
296281180db9Smartijn break;
296381180db9Smartijn case AX_DATA_TYPE_OID:
29640f9df26dSmartijn if (overflow == 1) {
29650f9df26dSmartijn data->avb_oid.aoi_idlen = UINT32_MAX;
29660f9df26dSmartijn continue;
29670f9df26dSmartijn } else if (j >= oid->aoi_idlen || overflow == -1) {
29680f9df26dSmartijn data->avb_oid.aoi_idlen = 0;
29690f9df26dSmartijn continue;
29700f9df26dSmartijn }
29710f9df26dSmartijn if (agentx_object_implied(axo, index->axv_axi))
29720f9df26dSmartijn data->avb_oid.aoi_idlen = oid->aoi_idlen - j;
29730f9df26dSmartijn else {
29740f9df26dSmartijn data->avb_oid.aoi_idlen = oid->aoi_id[j++];
29750f9df26dSmartijn if (data->avb_oid.aoi_idlen >=
29760f9df26dSmartijn AGENTX_OID_MAX_LEN - j) {
29770f9df26dSmartijn data->avb_oid.aoi_idlen = UINT32_MAX;
297881180db9Smartijn overflow = 1;
29790f9df26dSmartijn }
29800f9df26dSmartijn }
29810f9df26dSmartijn if (data->avb_oid.aoi_idlen == UINT32_MAX ||
29820f9df26dSmartijn data->avb_oid.aoi_idlen == 0)
298381180db9Smartijn continue;
298481180db9Smartijn for (k = 0; k < data->avb_oid.aoi_idlen; k++, j++) {
29850f9df26dSmartijn if (overflow == 1)
29860f9df26dSmartijn data->avb_oid.aoi_id[k] = UINT32_MAX;
29870f9df26dSmartijn else if (j >= oid->aoi_idlen || overflow == -1)
298881180db9Smartijn data->avb_oid.aoi_id[k] = 0;
29890f9df26dSmartijn else
29900f9df26dSmartijn data->avb_oid.aoi_id[k] =
29910f9df26dSmartijn oid->aoi_id[j];
299281180db9Smartijn }
29930f9df26dSmartijn j--;
299481180db9Smartijn break;
299581180db9Smartijn case AX_DATA_TYPE_IPADDRESS:
29960f9df26dSmartijn ipaddress = malloc(sizeof(*ipaddress));
299781180db9Smartijn if (ipaddress == NULL) {
299881180db9Smartijn agentx_log_axg_warn(axg,
299981180db9Smartijn "Failed to bind ipaddress index");
300081180db9Smartijn agentx_varbind_error_type(axv,
300181180db9Smartijn AX_PDU_ERROR_PROCESSINGERROR, 1);
300281180db9Smartijn return;
300381180db9Smartijn }
300481180db9Smartijn ipbytes = (unsigned char *)ipaddress;
300581180db9Smartijn for (k = 0; k < 4; k++, j++) {
30060f9df26dSmartijn if (j < oid->aoi_idlen && oid->aoi_id[j] > 255)
300781180db9Smartijn overflow = 1;
30080f9df26dSmartijn if (overflow == 1)
30090f9df26dSmartijn ipbytes[k] = 255;
30100f9df26dSmartijn else if (j >= oid->aoi_idlen || overflow == -1)
30110f9df26dSmartijn ipbytes[k] = 0;
30120f9df26dSmartijn else
30130f9df26dSmartijn ipbytes[k] = oid->aoi_id[j];
301481180db9Smartijn }
30150f9df26dSmartijn j--;
301681180db9Smartijn data->avb_ostring.aos_slen = sizeof(*ipaddress);
301781180db9Smartijn data->avb_ostring.aos_string =
301881180db9Smartijn (unsigned char *)ipaddress;
301981180db9Smartijn break;
302081180db9Smartijn default:
302181180db9Smartijn #ifdef AX_DEBUG
302281180db9Smartijn agentx_log_axg_fatalx(axg,
302381180db9Smartijn "%s: unexpected index type", __func__);
302481180db9Smartijn #else
302581180db9Smartijn agentx_log_axg_warnx(axg,
302681180db9Smartijn "%s: unexpected index type", __func__);
302781180db9Smartijn agentx_varbind_error_type(axv,
302881180db9Smartijn AX_PDU_ERROR_PROCESSINGERROR, 1);
302981180db9Smartijn return;
303081180db9Smartijn #endif
303181180db9Smartijn }
303281180db9Smartijn }
303381180db9Smartijn if (axv->axv_axg->axg_type == AX_PDU_TYPE_GET) {
30340f9df26dSmartijn if (j != oid->aoi_idlen || overflow) {
303581180db9Smartijn agentx_varbind_nosuchinstance(axv);
303681180db9Smartijn return;
303781180db9Smartijn }
303881180db9Smartijn }
303981180db9Smartijn
30400f9df26dSmartijn if (overflow == 1) {
304181180db9Smartijn axv->axv_include = 0;
30420f9df26dSmartijn } else if (overflow == -1) {
30430f9df26dSmartijn axv->axv_include = 1;
30440f9df26dSmartijn } else if (j < oid->aoi_idlen)
30450f9df26dSmartijn axv->axv_include = 0;
30460f9df26dSmartijn else if (j > oid->aoi_idlen)
30470f9df26dSmartijn axv->axv_include = 1;
304881180db9Smartijn if (agentx_varbind_request(axv) == AGENTX_REQUEST_TYPE_GETNEXT &&
304981180db9Smartijn !dynamic) {
305081180db9Smartijn agentx_varbind_endofmibview(axv);
305181180db9Smartijn return;
305281180db9Smartijn }
305381180db9Smartijn
305481180db9Smartijn axo->axo_get(axv);
305581180db9Smartijn }
305681180db9Smartijn
305781180db9Smartijn void
30581b6ededeSmartijn agentx_varbind_integer(struct agentx_varbind *axv, int32_t value)
305981180db9Smartijn {
306081180db9Smartijn axv->axv_vb.avb_type = AX_DATA_TYPE_INTEGER;
30611b6ededeSmartijn axv->axv_vb.avb_data.avb_int32 = value;
306281180db9Smartijn
306381180db9Smartijn agentx_varbind_finalize(axv);
306481180db9Smartijn }
306581180db9Smartijn
306681180db9Smartijn void
306781180db9Smartijn agentx_varbind_string(struct agentx_varbind *axv, const char *value)
306881180db9Smartijn {
306981180db9Smartijn agentx_varbind_nstring(axv, (const unsigned char *)value,
307081180db9Smartijn strlen(value));
307181180db9Smartijn }
307281180db9Smartijn
307381180db9Smartijn void
307481180db9Smartijn agentx_varbind_nstring(struct agentx_varbind *axv,
307581180db9Smartijn const unsigned char *value, size_t slen)
307681180db9Smartijn {
307781180db9Smartijn axv->axv_vb.avb_data.avb_ostring.aos_string = malloc(slen);
307881180db9Smartijn if (axv->axv_vb.avb_data.avb_ostring.aos_string == NULL) {
307981180db9Smartijn agentx_log_axg_warn(axv->axv_axg, "Couldn't bind string");
308081180db9Smartijn agentx_varbind_error_type(axv,
308181180db9Smartijn AX_PDU_ERROR_PROCESSINGERROR, 1);
308281180db9Smartijn return;
308381180db9Smartijn }
308481180db9Smartijn axv->axv_vb.avb_type = AX_DATA_TYPE_OCTETSTRING;
308581180db9Smartijn memcpy(axv->axv_vb.avb_data.avb_ostring.aos_string, value, slen);
308681180db9Smartijn axv->axv_vb.avb_data.avb_ostring.aos_slen = slen;
308781180db9Smartijn
308881180db9Smartijn agentx_varbind_finalize(axv);
308981180db9Smartijn }
309081180db9Smartijn
309181180db9Smartijn void
309281180db9Smartijn agentx_varbind_printf(struct agentx_varbind *axv, const char *fmt, ...)
309381180db9Smartijn {
309481180db9Smartijn va_list ap;
309581180db9Smartijn int r;
309681180db9Smartijn
309781180db9Smartijn axv->axv_vb.avb_type = AX_DATA_TYPE_OCTETSTRING;
309881180db9Smartijn va_start(ap, fmt);
309981180db9Smartijn r = vasprintf((char **)&(axv->axv_vb.avb_data.avb_ostring.aos_string),
310081180db9Smartijn fmt, ap);
310181180db9Smartijn va_end(ap);
310281180db9Smartijn if (r == -1) {
310381180db9Smartijn axv->axv_vb.avb_data.avb_ostring.aos_string = NULL;
310481180db9Smartijn agentx_log_axg_warn(axv->axv_axg, "Couldn't bind string");
31059c70cf54Smartijn agentx_varbind_error_type(axv, AX_PDU_ERROR_PROCESSINGERROR, 1);
310681180db9Smartijn return;
310781180db9Smartijn }
310881180db9Smartijn axv->axv_vb.avb_data.avb_ostring.aos_slen = r;
310981180db9Smartijn
311081180db9Smartijn agentx_varbind_finalize(axv);
311181180db9Smartijn }
311281180db9Smartijn
311381180db9Smartijn void
311481180db9Smartijn agentx_varbind_null(struct agentx_varbind *axv)
311581180db9Smartijn {
311681180db9Smartijn axv->axv_vb.avb_type = AX_DATA_TYPE_NULL;
311781180db9Smartijn
311881180db9Smartijn agentx_varbind_finalize(axv);
311981180db9Smartijn }
312081180db9Smartijn
312181180db9Smartijn void
312281180db9Smartijn agentx_varbind_oid(struct agentx_varbind *axv, const uint32_t oid[],
312381180db9Smartijn size_t oidlen)
312481180db9Smartijn {
31259c70cf54Smartijn const char *errstr;
312681180db9Smartijn
312781180db9Smartijn axv->axv_vb.avb_type = AX_DATA_TYPE_OID;
312881180db9Smartijn
31299c70cf54Smartijn if (agentx_oidfill(&(axv->axv_vb.avb_data.avb_oid),
31309c70cf54Smartijn oid, oidlen, &errstr) == -1) {
31319c70cf54Smartijn #ifdef AX_DEBUG
31329c70cf54Smartijn agentx_log_axg_fatalx(axv->axv_axg, "%s: %s", __func__, errstr);
31339c70cf54Smartijn #else
31349c70cf54Smartijn agentx_log_axg_warnx(axv->axv_axg, "%s: %s", __func__, errstr);
31359c70cf54Smartijn agentx_varbind_error_type(axv, AX_PDU_ERROR_PROCESSINGERROR, 1);
31369c70cf54Smartijn return;
31379c70cf54Smartijn #endif
31389c70cf54Smartijn }
313981180db9Smartijn
314081180db9Smartijn agentx_varbind_finalize(axv);
314181180db9Smartijn }
314281180db9Smartijn
314381180db9Smartijn void
314481180db9Smartijn agentx_varbind_object(struct agentx_varbind *axv,
314581180db9Smartijn struct agentx_object *axo)
314681180db9Smartijn {
314781180db9Smartijn agentx_varbind_oid(axv, axo->axo_oid.aoi_id,
314881180db9Smartijn axo->axo_oid.aoi_idlen);
314981180db9Smartijn }
315081180db9Smartijn
315181180db9Smartijn void
315281180db9Smartijn agentx_varbind_index(struct agentx_varbind *axv,
315381180db9Smartijn struct agentx_index *axi)
315481180db9Smartijn {
315581180db9Smartijn agentx_varbind_oid(axv, axi->axi_vb.avb_oid.aoi_id,
315681180db9Smartijn axi->axi_vb.avb_oid.aoi_idlen);
315781180db9Smartijn }
315881180db9Smartijn
315981180db9Smartijn
316081180db9Smartijn void
316181180db9Smartijn agentx_varbind_ipaddress(struct agentx_varbind *axv,
316281180db9Smartijn const struct in_addr *value)
316381180db9Smartijn {
316481180db9Smartijn axv->axv_vb.avb_type = AX_DATA_TYPE_IPADDRESS;
316581180db9Smartijn axv->axv_vb.avb_data.avb_ostring.aos_string = malloc(4);
316681180db9Smartijn if (axv->axv_vb.avb_data.avb_ostring.aos_string == NULL) {
316781180db9Smartijn agentx_log_axg_warn(axv->axv_axg, "Couldn't bind ipaddress");
316881180db9Smartijn agentx_varbind_error_type(axv,
316981180db9Smartijn AX_PDU_ERROR_PROCESSINGERROR, 1);
317081180db9Smartijn return;
317181180db9Smartijn }
317281180db9Smartijn memcpy(axv->axv_vb.avb_data.avb_ostring.aos_string, value, 4);
317381180db9Smartijn axv->axv_vb.avb_data.avb_ostring.aos_slen = 4;
317481180db9Smartijn
317581180db9Smartijn agentx_varbind_finalize(axv);
317681180db9Smartijn }
317781180db9Smartijn
317881180db9Smartijn void
317981180db9Smartijn agentx_varbind_counter32(struct agentx_varbind *axv, uint32_t value)
318081180db9Smartijn {
318181180db9Smartijn axv->axv_vb.avb_type = AX_DATA_TYPE_COUNTER32;
318281180db9Smartijn axv->axv_vb.avb_data.avb_uint32 = value;
318381180db9Smartijn
318481180db9Smartijn agentx_varbind_finalize(axv);
318581180db9Smartijn }
318681180db9Smartijn
318781180db9Smartijn void
318881180db9Smartijn agentx_varbind_gauge32(struct agentx_varbind *axv, uint32_t value)
318981180db9Smartijn {
319081180db9Smartijn axv->axv_vb.avb_type = AX_DATA_TYPE_GAUGE32;
319181180db9Smartijn axv->axv_vb.avb_data.avb_uint32 = value;
319281180db9Smartijn
319381180db9Smartijn agentx_varbind_finalize(axv);
319481180db9Smartijn }
319581180db9Smartijn
319681180db9Smartijn void
3197036f0da0Smartijn agentx_varbind_unsigned32(struct agentx_varbind *axv, uint32_t value)
3198036f0da0Smartijn {
3199036f0da0Smartijn agentx_varbind_gauge32(axv, value);
3200036f0da0Smartijn }
3201036f0da0Smartijn
3202036f0da0Smartijn void
320381180db9Smartijn agentx_varbind_timeticks(struct agentx_varbind *axv, uint32_t value)
320481180db9Smartijn {
320581180db9Smartijn axv->axv_vb.avb_type = AX_DATA_TYPE_TIMETICKS;
320681180db9Smartijn axv->axv_vb.avb_data.avb_uint32 = value;
320781180db9Smartijn
320881180db9Smartijn agentx_varbind_finalize(axv);
320981180db9Smartijn }
321081180db9Smartijn
321181180db9Smartijn void
321281180db9Smartijn agentx_varbind_opaque(struct agentx_varbind *axv, const char *string,
321381180db9Smartijn size_t strlen)
321481180db9Smartijn {
321581180db9Smartijn axv->axv_vb.avb_type = AX_DATA_TYPE_OPAQUE;
321681180db9Smartijn axv->axv_vb.avb_data.avb_ostring.aos_string = malloc(strlen);
321781180db9Smartijn if (axv->axv_vb.avb_data.avb_ostring.aos_string == NULL) {
321881180db9Smartijn agentx_log_axg_warn(axv->axv_axg, "Couldn't bind opaque");
321981180db9Smartijn agentx_varbind_error_type(axv,
322081180db9Smartijn AX_PDU_ERROR_PROCESSINGERROR, 1);
322181180db9Smartijn return;
322281180db9Smartijn }
322381180db9Smartijn memcpy(axv->axv_vb.avb_data.avb_ostring.aos_string, string, strlen);
322481180db9Smartijn axv->axv_vb.avb_data.avb_ostring.aos_slen = strlen;
322581180db9Smartijn
322681180db9Smartijn agentx_varbind_finalize(axv);
322781180db9Smartijn }
322881180db9Smartijn
322981180db9Smartijn void
323081180db9Smartijn agentx_varbind_counter64(struct agentx_varbind *axv, uint64_t value)
323181180db9Smartijn {
323281180db9Smartijn axv->axv_vb.avb_type = AX_DATA_TYPE_COUNTER64;
323381180db9Smartijn axv->axv_vb.avb_data.avb_uint64 = value;
323481180db9Smartijn
323581180db9Smartijn agentx_varbind_finalize(axv);
323681180db9Smartijn }
323781180db9Smartijn
323881180db9Smartijn void
323981180db9Smartijn agentx_varbind_notfound(struct agentx_varbind *axv)
324081180db9Smartijn {
324181180db9Smartijn if (axv->axv_indexlen == 0) {
324281180db9Smartijn #ifdef AX_DEBUG
324381180db9Smartijn agentx_log_axg_fatalx(axv->axv_axg, "%s invalid call",
324481180db9Smartijn __func__);
324581180db9Smartijn #else
324681180db9Smartijn agentx_log_axg_warnx(axv->axv_axg, "%s invalid call",
324781180db9Smartijn __func__);
324881180db9Smartijn agentx_varbind_error_type(axv,
324981180db9Smartijn AX_PDU_ERROR_GENERR, 1);
325081180db9Smartijn #endif
325181180db9Smartijn } else if (axv->axv_axg->axg_type == AX_PDU_TYPE_GET)
325281180db9Smartijn agentx_varbind_nosuchinstance(axv);
325381180db9Smartijn else
325481180db9Smartijn agentx_varbind_endofmibview(axv);
325581180db9Smartijn }
325681180db9Smartijn
325781180db9Smartijn void
325881180db9Smartijn agentx_varbind_error(struct agentx_varbind *axv)
325981180db9Smartijn {
326081180db9Smartijn agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 1);
326181180db9Smartijn }
326281180db9Smartijn
326381180db9Smartijn static void
326481180db9Smartijn agentx_varbind_error_type(struct agentx_varbind *axv,
326581180db9Smartijn enum ax_pdu_error error, int done)
326681180db9Smartijn {
326781180db9Smartijn if (axv->axv_error == AX_PDU_ERROR_NOERROR) {
326881180db9Smartijn axv->axv_error = error;
326981180db9Smartijn }
327081180db9Smartijn
327181180db9Smartijn if (done) {
327281180db9Smartijn axv->axv_vb.avb_type = AX_DATA_TYPE_NULL;
327381180db9Smartijn
327481180db9Smartijn agentx_varbind_finalize(axv);
327581180db9Smartijn }
327681180db9Smartijn }
327781180db9Smartijn
327881180db9Smartijn static void
327981180db9Smartijn agentx_varbind_finalize(struct agentx_varbind *axv)
328081180db9Smartijn {
328181180db9Smartijn struct agentx_get *axg = axv->axv_axg;
328281180db9Smartijn struct ax_oid oid;
328381180db9Smartijn union ax_data *data;
328481180db9Smartijn size_t i, j;
328581180db9Smartijn int cmp;
328681180db9Smartijn
328781180db9Smartijn if (axv->axv_error != AX_PDU_ERROR_NOERROR) {
328881180db9Smartijn bcopy(&(axv->axv_start), &(axv->axv_vb.avb_oid),
328981180db9Smartijn sizeof(axv->axv_start));
329081180db9Smartijn goto done;
329181180db9Smartijn }
329281180db9Smartijn bcopy(&(axv->axv_axo->axo_oid), &oid, sizeof(oid));
329381180db9Smartijn if (axv->axv_indexlen == 0)
329481180db9Smartijn ax_oid_add(&oid, 0);
329581180db9Smartijn for (i = 0; i < axv->axv_indexlen; i++) {
329681180db9Smartijn data = &(axv->axv_index[i].axv_idata);
329781180db9Smartijn switch (axv->axv_index[i].axv_axi->axi_vb.avb_type) {
329881180db9Smartijn case AX_DATA_TYPE_INTEGER:
32991b6ededeSmartijn if (ax_oid_add(&oid, data->avb_int32) == -1)
330081180db9Smartijn goto fail;
330181180db9Smartijn break;
330281180db9Smartijn case AX_DATA_TYPE_OCTETSTRING:
330381180db9Smartijn if (!agentx_object_implied(axv->axv_axo,
330481180db9Smartijn axv->axv_index[i].axv_axi)) {
330581180db9Smartijn if (ax_oid_add(&oid,
330681180db9Smartijn data->avb_ostring.aos_slen) == -1)
330781180db9Smartijn goto fail;
330881180db9Smartijn }
330981180db9Smartijn for (j = 0; j < data->avb_ostring.aos_slen; j++) {
331081180db9Smartijn if (ax_oid_add(&oid,
331181180db9Smartijn (uint8_t)data->avb_ostring.aos_string[j]) ==
331281180db9Smartijn -1)
331381180db9Smartijn goto fail;
331481180db9Smartijn }
331581180db9Smartijn break;
331681180db9Smartijn case AX_DATA_TYPE_OID:
331781180db9Smartijn if (!agentx_object_implied(axv->axv_axo,
331881180db9Smartijn axv->axv_index[i].axv_axi)) {
331981180db9Smartijn if (ax_oid_add(&oid,
332081180db9Smartijn data->avb_oid.aoi_idlen) == -1)
332181180db9Smartijn goto fail;
332281180db9Smartijn }
332381180db9Smartijn for (j = 0; j < data->avb_oid.aoi_idlen; j++) {
332481180db9Smartijn if (ax_oid_add(&oid,
332581180db9Smartijn data->avb_oid.aoi_id[j]) == -1)
332681180db9Smartijn goto fail;
332781180db9Smartijn }
332881180db9Smartijn break;
332981180db9Smartijn case AX_DATA_TYPE_IPADDRESS:
333081180db9Smartijn for (j = 0; j < 4; j++) {
333181180db9Smartijn if (ax_oid_add(&oid,
333281180db9Smartijn data->avb_ostring.aos_string == NULL ? 0 :
333381180db9Smartijn (uint8_t)data->avb_ostring.aos_string[j]) ==
333481180db9Smartijn -1)
333581180db9Smartijn goto fail;
333681180db9Smartijn }
333781180db9Smartijn break;
333881180db9Smartijn default:
333981180db9Smartijn #ifdef AX_DEBUG
334081180db9Smartijn agentx_log_axg_fatalx(axg,
334181180db9Smartijn "%s: unsupported index type", __func__);
334281180db9Smartijn #else
334381180db9Smartijn bcopy(&(axv->axv_start), &(axv->axv_vb.avb_oid),
334481180db9Smartijn sizeof(axv->axv_start));
334581180db9Smartijn axv->axv_error = AX_PDU_ERROR_PROCESSINGERROR;
334681180db9Smartijn agentx_object_unlock(axv->axv_axo);
334781180db9Smartijn agentx_get_finalize(axv->axv_axg);
334881180db9Smartijn return;
334981180db9Smartijn #endif
335081180db9Smartijn }
335181180db9Smartijn }
3352*c5fcbd5aSmartijn cmp = ax_oid_cmp(&oid, &(axv->axv_vb.avb_oid));
3353*c5fcbd5aSmartijn switch (agentx_varbind_request(axv)) {
3354*c5fcbd5aSmartijn case AGENTX_REQUEST_TYPE_GET:
3355*c5fcbd5aSmartijn if (cmp != 0) {
3356*c5fcbd5aSmartijn #ifdef AX_DEBUG
3357*c5fcbd5aSmartijn agentx_log_axg_fatalx(axg, "index changed");
3358*c5fcbd5aSmartijn #else
3359*c5fcbd5aSmartijn agentx_log_axg_warnx(axg, "index changed");
3360*c5fcbd5aSmartijn bcopy(&(axv->axv_start), &(axv->axv_vb.avb_oid),
3361*c5fcbd5aSmartijn sizeof(axv->axv_start));
3362*c5fcbd5aSmartijn axv->axv_error = AX_PDU_ERROR_GENERR;
3363*c5fcbd5aSmartijn break;
3364*c5fcbd5aSmartijn #endif
3365*c5fcbd5aSmartijn }
3366*c5fcbd5aSmartijn break;
3367*c5fcbd5aSmartijn case AGENTX_REQUEST_TYPE_GETNEXT:
3368*c5fcbd5aSmartijn if (cmp <= 0) {
336981180db9Smartijn #ifdef AX_DEBUG
337081180db9Smartijn agentx_log_axg_fatalx(axg, "indices not incremented");
337181180db9Smartijn #else
337281180db9Smartijn agentx_log_axg_warnx(axg, "indices not incremented");
337381180db9Smartijn bcopy(&(axv->axv_start), &(axv->axv_vb.avb_oid),
337481180db9Smartijn sizeof(axv->axv_start));
337581180db9Smartijn axv->axv_error = AX_PDU_ERROR_GENERR;
3376*c5fcbd5aSmartijn break;
337781180db9Smartijn #endif
3378*c5fcbd5aSmartijn }
3379*c5fcbd5aSmartijn /* FALLTHROUGH */
3380*c5fcbd5aSmartijn case AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE:
3381*c5fcbd5aSmartijn if (cmp < 0) {
3382*c5fcbd5aSmartijn #ifdef AX_DEBUG
3383*c5fcbd5aSmartijn agentx_log_axg_fatalx(axg, "index decremented");
3384*c5fcbd5aSmartijn #else
3385*c5fcbd5aSmartijn agentx_log_axg_warnx(axg, "index decremented");
3386*c5fcbd5aSmartijn bcopy(&(axv->axv_start), &(axv->axv_vb.avb_oid),
3387*c5fcbd5aSmartijn sizeof(axv->axv_start));
3388*c5fcbd5aSmartijn axv->axv_error = AX_PDU_ERROR_GENERR;
3389*c5fcbd5aSmartijn break;
3390*c5fcbd5aSmartijn #endif
3391*c5fcbd5aSmartijn }
3392*c5fcbd5aSmartijn if (axv->axv_end.aoi_idlen != 0 &&
3393*c5fcbd5aSmartijn ax_oid_cmp(&oid, &(axv->axv_end)) >= 0) {
3394*c5fcbd5aSmartijn agentx_varbind_endofmibview(axv);
3395*c5fcbd5aSmartijn return;
3396*c5fcbd5aSmartijn }
339781180db9Smartijn bcopy(&oid, &(axv->axv_vb.avb_oid), sizeof(oid));
3398*c5fcbd5aSmartijn }
339981180db9Smartijn done:
340081180db9Smartijn agentx_object_unlock(axv->axv_axo);
340181180db9Smartijn agentx_get_finalize(axv->axv_axg);
340281180db9Smartijn return;
34039dbe2cd1Smartijn
34049dbe2cd1Smartijn fail:
340581180db9Smartijn agentx_log_axg_warnx(axg, "oid too large");
340681180db9Smartijn bcopy(&(axv->axv_start), &(axv->axv_vb.avb_oid),
340781180db9Smartijn sizeof(axv->axv_start));
340881180db9Smartijn axv->axv_error = AX_PDU_ERROR_GENERR;
340981180db9Smartijn agentx_object_unlock(axv->axv_axo);
341081180db9Smartijn agentx_get_finalize(axv->axv_axg);
341181180db9Smartijn }
341281180db9Smartijn
341381180db9Smartijn static void
341481180db9Smartijn agentx_varbind_nosuchobject(struct agentx_varbind *axv)
341581180db9Smartijn {
341681180db9Smartijn axv->axv_vb.avb_type = AX_DATA_TYPE_NOSUCHOBJECT;
341781180db9Smartijn
341881180db9Smartijn if (axv->axv_axo != NULL)
341981180db9Smartijn agentx_object_unlock(axv->axv_axo);
342081180db9Smartijn agentx_get_finalize(axv->axv_axg);
342181180db9Smartijn }
342281180db9Smartijn
342381180db9Smartijn static void
342481180db9Smartijn agentx_varbind_nosuchinstance(struct agentx_varbind *axv)
342581180db9Smartijn {
342681180db9Smartijn axv->axv_vb.avb_type = AX_DATA_TYPE_NOSUCHINSTANCE;
342781180db9Smartijn
342881180db9Smartijn if (axv->axv_axo != NULL)
342981180db9Smartijn agentx_object_unlock(axv->axv_axo);
343081180db9Smartijn agentx_get_finalize(axv->axv_axg);
343181180db9Smartijn }
343281180db9Smartijn
343381180db9Smartijn static void
343481180db9Smartijn agentx_varbind_endofmibview(struct agentx_varbind *axv)
343581180db9Smartijn {
343681180db9Smartijn struct agentx_object *axo;
343781180db9Smartijn struct ax_varbind *vb;
343881180db9Smartijn struct agentx_varbind_index *index;
343981180db9Smartijn size_t i;
344081180db9Smartijn
344181180db9Smartijn #ifdef AX_DEBUG
344281180db9Smartijn if (axv->axv_axg->axg_type != AX_PDU_TYPE_GETNEXT &&
344381180db9Smartijn axv->axv_axg->axg_type != AX_PDU_TYPE_GETBULK)
344481180db9Smartijn agentx_log_axg_fatalx(axv->axv_axg,
344581180db9Smartijn "%s: invalid request type", __func__);
344681180db9Smartijn #endif
344781180db9Smartijn
344881180db9Smartijn if (axv->axv_axo != NULL &&
344981180db9Smartijn (axo = RB_NEXT(axc_objects, &(axc->axc_objects),
345081180db9Smartijn axv->axv_axo)) != NULL &&
345181180db9Smartijn ax_oid_cmp(&(axo->axo_oid), &(axv->axv_end)) < 0) {
345281180db9Smartijn bcopy(&(axo->axo_oid), &(axv->axv_vb.avb_oid),
345381180db9Smartijn sizeof(axo->axo_oid));
345481180db9Smartijn axv->axv_include = 1;
345581180db9Smartijn for (i = 0; i < axv->axv_indexlen; i++) {
345681180db9Smartijn index = &(axv->axv_index[i]);
345781180db9Smartijn vb = &(index->axv_axi->axi_vb);
345881180db9Smartijn if (vb->avb_type == AX_DATA_TYPE_OCTETSTRING ||
345981180db9Smartijn vb->avb_type == AX_DATA_TYPE_IPADDRESS)
346081180db9Smartijn free(index->axv_idata.avb_ostring.aos_string);
346181180db9Smartijn }
346281180db9Smartijn bzero(&(axv->axv_index), sizeof(axv->axv_index));
346381180db9Smartijn agentx_object_unlock(axv->axv_axo);
346481180db9Smartijn agentx_varbind_start(axv);
346581180db9Smartijn return;
346681180db9Smartijn }
346781180db9Smartijn
3468c812f9ceSmartijn bcopy(&(axv->axv_start), &(axv->axv_vb.avb_oid),
3469c812f9ceSmartijn sizeof(axv->axv_start));
347081180db9Smartijn axv->axv_vb.avb_type = AX_DATA_TYPE_ENDOFMIBVIEW;
347181180db9Smartijn
347281180db9Smartijn if (axv->axv_axo != NULL)
347381180db9Smartijn agentx_object_unlock(axv->axv_axo);
347481180db9Smartijn agentx_get_finalize(axv->axv_axg);
347581180db9Smartijn }
347681180db9Smartijn
347781180db9Smartijn enum agentx_request_type
347881180db9Smartijn agentx_varbind_request(struct agentx_varbind *axv)
347981180db9Smartijn {
348081180db9Smartijn if (axv->axv_axg->axg_type == AX_PDU_TYPE_GET)
348181180db9Smartijn return AGENTX_REQUEST_TYPE_GET;
34820f9df26dSmartijn if (axv->axv_include)
348381180db9Smartijn return AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE;
348481180db9Smartijn return AGENTX_REQUEST_TYPE_GETNEXT;
348581180db9Smartijn }
348681180db9Smartijn
348781180db9Smartijn struct agentx_object *
348881180db9Smartijn agentx_varbind_get_object(struct agentx_varbind *axv)
348981180db9Smartijn {
349081180db9Smartijn return axv->axv_axo;
349181180db9Smartijn }
349281180db9Smartijn
34931b6ededeSmartijn int32_t
349481180db9Smartijn agentx_varbind_get_index_integer(struct agentx_varbind *axv,
349581180db9Smartijn struct agentx_index *axi)
349681180db9Smartijn {
349781180db9Smartijn size_t i;
349881180db9Smartijn
349981180db9Smartijn if (axi->axi_vb.avb_type != AX_DATA_TYPE_INTEGER) {
350081180db9Smartijn #ifdef AX_DEBUG
350181180db9Smartijn agentx_log_axg_fatalx(axv->axv_axg, "invalid index type");
350281180db9Smartijn #else
350381180db9Smartijn agentx_log_axg_warnx(axv->axv_axg, "invalid index type");
350481180db9Smartijn agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
350581180db9Smartijn return 0;
350681180db9Smartijn #endif
350781180db9Smartijn }
350881180db9Smartijn
350981180db9Smartijn for (i = 0; i < axv->axv_indexlen; i++) {
351081180db9Smartijn if (axv->axv_index[i].axv_axi == axi)
35111b6ededeSmartijn return axv->axv_index[i].axv_idata.avb_int32;
351281180db9Smartijn }
351381180db9Smartijn #ifdef AX_DEBUG
351481180db9Smartijn agentx_log_axg_fatalx(axv->axv_axg, "invalid index");
351581180db9Smartijn #else
351681180db9Smartijn agentx_log_axg_warnx(axv->axv_axg, "invalid index");
351781180db9Smartijn agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
351881180db9Smartijn return 0;
351981180db9Smartijn #endif
352081180db9Smartijn }
352181180db9Smartijn
352281180db9Smartijn const unsigned char *
352381180db9Smartijn agentx_varbind_get_index_string(struct agentx_varbind *axv,
352481180db9Smartijn struct agentx_index *axi, size_t *slen, int *implied)
352581180db9Smartijn {
352681180db9Smartijn struct agentx_varbind_index *index;
352781180db9Smartijn size_t i;
352881180db9Smartijn
352981180db9Smartijn if (axi->axi_vb.avb_type != AX_DATA_TYPE_OCTETSTRING) {
353081180db9Smartijn #ifdef AX_DEBUG
353181180db9Smartijn agentx_log_axg_fatalx(axv->axv_axg, "invalid index type");
353281180db9Smartijn #else
353381180db9Smartijn agentx_log_axg_warnx(axv->axv_axg, "invalid index type");
353481180db9Smartijn agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
353581180db9Smartijn *slen = 0;
353681180db9Smartijn *implied = 0;
353781180db9Smartijn return NULL;
353881180db9Smartijn #endif
353981180db9Smartijn }
354081180db9Smartijn
354181180db9Smartijn for (i = 0; i < axv->axv_indexlen; i++) {
354281180db9Smartijn if (axv->axv_index[i].axv_axi == axi) {
354381180db9Smartijn index = &(axv->axv_index[i]);
354481180db9Smartijn *slen = index->axv_idata.avb_ostring.aos_slen;
354581180db9Smartijn *implied = agentx_object_implied(axv->axv_axo, axi);
354681180db9Smartijn return index->axv_idata.avb_ostring.aos_string;
354781180db9Smartijn }
354881180db9Smartijn }
354981180db9Smartijn
355081180db9Smartijn #ifdef AX_DEBUG
355181180db9Smartijn agentx_log_axg_fatalx(axv->axv_axg, "invalid index");
355281180db9Smartijn #else
355381180db9Smartijn agentx_log_axg_warnx(axv->axv_axg, "invalid index");
355481180db9Smartijn agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
355581180db9Smartijn *slen = 0;
355681180db9Smartijn *implied = 0;
355781180db9Smartijn return NULL;
355881180db9Smartijn #endif
355981180db9Smartijn }
356081180db9Smartijn
356181180db9Smartijn const uint32_t *
356281180db9Smartijn agentx_varbind_get_index_oid(struct agentx_varbind *axv,
356381180db9Smartijn struct agentx_index *axi, size_t *oidlen, int *implied)
356481180db9Smartijn {
356581180db9Smartijn struct agentx_varbind_index *index;
356681180db9Smartijn size_t i;
356781180db9Smartijn
356881180db9Smartijn if (axi->axi_vb.avb_type != AX_DATA_TYPE_OID) {
356981180db9Smartijn #ifdef AX_DEBUG
357081180db9Smartijn agentx_log_axg_fatalx(axv->axv_axg, "invalid index type");
357181180db9Smartijn #else
357281180db9Smartijn agentx_log_axg_warnx(axv->axv_axg, "invalid index type");
357381180db9Smartijn agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
357481180db9Smartijn *oidlen = 0;
357581180db9Smartijn *implied = 0;
357681180db9Smartijn return NULL;
357781180db9Smartijn #endif
357881180db9Smartijn }
357981180db9Smartijn
358081180db9Smartijn for (i = 0; i < axv->axv_indexlen; i++) {
358181180db9Smartijn if (axv->axv_index[i].axv_axi == axi) {
358281180db9Smartijn index = &(axv->axv_index[i]);
358381180db9Smartijn *oidlen = index->axv_idata.avb_oid.aoi_idlen;
358481180db9Smartijn *implied = agentx_object_implied(axv->axv_axo, axi);
358581180db9Smartijn return index->axv_idata.avb_oid.aoi_id;
358681180db9Smartijn }
358781180db9Smartijn }
358881180db9Smartijn
358981180db9Smartijn #ifdef AX_DEBUG
359081180db9Smartijn agentx_log_axg_fatalx(axv->axv_axg, "invalid index");
359181180db9Smartijn #else
359281180db9Smartijn agentx_log_axg_warnx(axv->axv_axg, "invalid index");
359381180db9Smartijn agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
359481180db9Smartijn *oidlen = 0;
359581180db9Smartijn *implied = 0;
359681180db9Smartijn return NULL;
359781180db9Smartijn #endif
359881180db9Smartijn }
359981180db9Smartijn
360081180db9Smartijn const struct in_addr *
360181180db9Smartijn agentx_varbind_get_index_ipaddress(struct agentx_varbind *axv,
360281180db9Smartijn struct agentx_index *axi)
360381180db9Smartijn {
360481180db9Smartijn static struct in_addr nuladdr = {0};
360581180db9Smartijn struct agentx_varbind_index *index;
360681180db9Smartijn size_t i;
360781180db9Smartijn
360881180db9Smartijn if (axi->axi_vb.avb_type != AX_DATA_TYPE_IPADDRESS) {
360981180db9Smartijn #ifdef AX_DEBUG
361081180db9Smartijn agentx_log_axg_fatalx(axv->axv_axg, "invalid index type");
361181180db9Smartijn #else
361281180db9Smartijn agentx_log_axg_warnx(axv->axv_axg, "invalid index type");
361381180db9Smartijn agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
361481180db9Smartijn return NULL;
361581180db9Smartijn #endif
361681180db9Smartijn }
361781180db9Smartijn
361881180db9Smartijn for (i = 0; i < axv->axv_indexlen; i++) {
361981180db9Smartijn if (axv->axv_index[i].axv_axi == axi) {
362081180db9Smartijn index = &(axv->axv_index[i]);
362181180db9Smartijn if (index->axv_idata.avb_ostring.aos_string == NULL)
362281180db9Smartijn return &nuladdr;
362381180db9Smartijn return (struct in_addr *)
362481180db9Smartijn index->axv_idata.avb_ostring.aos_string;
362581180db9Smartijn }
362681180db9Smartijn }
362781180db9Smartijn
362881180db9Smartijn #ifdef AX_DEBUG
362981180db9Smartijn agentx_log_axg_fatalx(axv->axv_axg, "invalid index");
363081180db9Smartijn #else
363181180db9Smartijn agentx_log_axg_warnx(axv->axv_axg, "invalid index");
363281180db9Smartijn agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
363381180db9Smartijn return NULL;
363481180db9Smartijn #endif
363581180db9Smartijn }
363681180db9Smartijn
363781180db9Smartijn void
363881180db9Smartijn agentx_varbind_set_index_integer(struct agentx_varbind *axv,
36391b6ededeSmartijn struct agentx_index *axi, int32_t value)
364081180db9Smartijn {
364181180db9Smartijn size_t i;
364281180db9Smartijn
364381180db9Smartijn if (axi->axi_vb.avb_type != AX_DATA_TYPE_INTEGER) {
364481180db9Smartijn #ifdef AX_DEBUG
364581180db9Smartijn agentx_log_axg_fatalx(axv->axv_axg, "invalid index type");
364681180db9Smartijn #else
364781180db9Smartijn agentx_log_axg_warnx(axv->axv_axg, "invalid index type");
364881180db9Smartijn agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
364981180db9Smartijn return;
365081180db9Smartijn #endif
365181180db9Smartijn }
365281180db9Smartijn
36531b6ededeSmartijn if (value < 0) {
36541b6ededeSmartijn #ifdef AX_DEBUG
36551b6ededeSmartijn agentx_log_axg_fatalx(axv->axv_axg, "invalid index value");
36561b6ededeSmartijn #else
36571b6ededeSmartijn agentx_log_axg_warnx(axv->axv_axg, "invalid index value");
36581b6ededeSmartijn agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
36591b6ededeSmartijn return;
36601b6ededeSmartijn #endif
36611b6ededeSmartijn }
36621b6ededeSmartijn
366381180db9Smartijn for (i = 0; i < axv->axv_indexlen; i++) {
366481180db9Smartijn if (axv->axv_index[i].axv_axi == axi) {
366581180db9Smartijn if (axv->axv_axg->axg_type == AX_PDU_TYPE_GET &&
36661b6ededeSmartijn axv->axv_index[i].axv_idata.avb_int32 != value) {
366781180db9Smartijn #ifdef AX_DEBUG
366881180db9Smartijn agentx_log_axg_fatalx(axv->axv_axg,
366981180db9Smartijn "can't change index on GET");
367081180db9Smartijn #else
367181180db9Smartijn agentx_log_axg_warnx(axv->axv_axg,
367281180db9Smartijn "can't change index on GET");
367381180db9Smartijn agentx_varbind_error_type(axv,
367481180db9Smartijn AX_PDU_ERROR_GENERR, 0);
367581180db9Smartijn return;
367681180db9Smartijn #endif
367781180db9Smartijn }
36781b6ededeSmartijn axv->axv_index[i].axv_idata.avb_int32 = value;
367981180db9Smartijn return;
368081180db9Smartijn }
368181180db9Smartijn }
368281180db9Smartijn #ifdef AX_DEBUG
368381180db9Smartijn agentx_log_axg_fatalx(axv->axv_axg, "invalid index");
368481180db9Smartijn #else
368581180db9Smartijn agentx_log_axg_warnx(axv->axv_axg, "invalid index");
368681180db9Smartijn agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
368781180db9Smartijn #endif
368881180db9Smartijn }
368981180db9Smartijn
369081180db9Smartijn void
369181180db9Smartijn agentx_varbind_set_index_string(struct agentx_varbind *axv,
369281180db9Smartijn struct agentx_index *axi, const char *value)
369381180db9Smartijn {
369481180db9Smartijn agentx_varbind_set_index_nstring(axv, axi,
369581180db9Smartijn (const unsigned char *)value, strlen(value));
369681180db9Smartijn }
369781180db9Smartijn
369881180db9Smartijn void
369981180db9Smartijn agentx_varbind_set_index_nstring(struct agentx_varbind *axv,
370081180db9Smartijn struct agentx_index *axi, const unsigned char *value, size_t slen)
370181180db9Smartijn {
370281180db9Smartijn struct ax_ostring *curvalue;
370381180db9Smartijn unsigned char *nstring;
370481180db9Smartijn size_t i;
370581180db9Smartijn
370681180db9Smartijn if (axi->axi_vb.avb_type != AX_DATA_TYPE_OCTETSTRING) {
370781180db9Smartijn #ifdef AX_DEBUG
370881180db9Smartijn agentx_log_axg_fatalx(axv->axv_axg, "invalid index type");
370981180db9Smartijn #else
371081180db9Smartijn agentx_log_axg_warnx(axv->axv_axg, "invalid index type");
371181180db9Smartijn agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
371281180db9Smartijn return;
371381180db9Smartijn #endif
371481180db9Smartijn }
371581180db9Smartijn
371681180db9Smartijn for (i = 0; i < axv->axv_indexlen; i++) {
371781180db9Smartijn if (axv->axv_index[i].axv_axi == axi) {
371881180db9Smartijn if (axi->axi_vb.avb_data.avb_ostring.aos_slen != 0 &&
371981180db9Smartijn axi->axi_vb.avb_data.avb_ostring.aos_slen != slen) {
372081180db9Smartijn #ifdef AX_DEBUG
372181180db9Smartijn agentx_log_axg_fatalx(axv->axv_axg,
372281180db9Smartijn "invalid string length on explicit length "
372381180db9Smartijn "string");
372481180db9Smartijn #else
372581180db9Smartijn agentx_log_axg_warnx(axv->axv_axg,
372681180db9Smartijn "invalid string length on explicit length "
372781180db9Smartijn "string");
372881180db9Smartijn agentx_varbind_error_type(axv,
372981180db9Smartijn AX_PDU_ERROR_GENERR, 0);
373081180db9Smartijn return;
373181180db9Smartijn #endif
373281180db9Smartijn }
373381180db9Smartijn curvalue = &(axv->axv_index[i].axv_idata.avb_ostring);
373481180db9Smartijn if (axv->axv_axg->axg_type == AX_PDU_TYPE_GET &&
373581180db9Smartijn (curvalue->aos_slen != slen ||
373681180db9Smartijn memcmp(curvalue->aos_string, value, slen) != 0)) {
373781180db9Smartijn #ifdef AX_DEBUG
373881180db9Smartijn agentx_log_axg_fatalx(axv->axv_axg,
373981180db9Smartijn "can't change index on GET");
374081180db9Smartijn #else
374181180db9Smartijn agentx_log_axg_warnx(axv->axv_axg,
374281180db9Smartijn "can't change index on GET");
374381180db9Smartijn agentx_varbind_error_type(axv,
374481180db9Smartijn AX_PDU_ERROR_GENERR, 0);
374581180db9Smartijn return;
374681180db9Smartijn #endif
374781180db9Smartijn }
374881180db9Smartijn if ((nstring = recallocarray(curvalue->aos_string,
374981180db9Smartijn curvalue->aos_slen + 1, slen + 1, 1)) == NULL) {
375081180db9Smartijn agentx_log_axg_warn(axv->axv_axg,
375181180db9Smartijn "Failed to bind string index");
375281180db9Smartijn agentx_varbind_error_type(axv,
375381180db9Smartijn AX_PDU_ERROR_PROCESSINGERROR, 0);
375481180db9Smartijn return;
375581180db9Smartijn }
375681180db9Smartijn curvalue->aos_string = nstring;
375781180db9Smartijn memcpy(nstring, value, slen);
375881180db9Smartijn curvalue->aos_slen = slen;
375981180db9Smartijn return;
376081180db9Smartijn }
376181180db9Smartijn }
376281180db9Smartijn #ifdef AX_DEBUG
376381180db9Smartijn agentx_log_axg_fatalx(axv->axv_axg, "invalid index");
376481180db9Smartijn #else
376581180db9Smartijn agentx_log_axg_warnx(axv->axv_axg, "invalid index");
376681180db9Smartijn agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
376781180db9Smartijn #endif
376881180db9Smartijn }
376981180db9Smartijn
377081180db9Smartijn void
377181180db9Smartijn agentx_varbind_set_index_oid(struct agentx_varbind *axv,
377281180db9Smartijn struct agentx_index *axi, const uint32_t *value, size_t oidlen)
377381180db9Smartijn {
377481180db9Smartijn struct ax_oid *curvalue, oid;
37759c70cf54Smartijn const char *errstr;
377681180db9Smartijn size_t i;
377781180db9Smartijn
377881180db9Smartijn if (axi->axi_vb.avb_type != AX_DATA_TYPE_OID) {
377981180db9Smartijn #ifdef AX_DEBUG
378081180db9Smartijn agentx_log_axg_fatalx(axv->axv_axg, "invalid index type");
378181180db9Smartijn #else
378281180db9Smartijn agentx_log_axg_warnx(axv->axv_axg, "invalid index type");
378381180db9Smartijn agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
378481180db9Smartijn return;
378581180db9Smartijn #endif
378681180db9Smartijn }
378781180db9Smartijn
378881180db9Smartijn for (i = 0; i < axv->axv_indexlen; i++) {
378981180db9Smartijn if (axv->axv_index[i].axv_axi == axi) {
379081180db9Smartijn if (axi->axi_vb.avb_data.avb_oid.aoi_idlen != 0 &&
379181180db9Smartijn axi->axi_vb.avb_data.avb_oid.aoi_idlen != oidlen) {
379281180db9Smartijn #ifdef AX_DEBUG
379381180db9Smartijn agentx_log_axg_fatalx(axv->axv_axg,
379481180db9Smartijn "invalid oid length on explicit length "
379581180db9Smartijn "oid");
379681180db9Smartijn #else
379781180db9Smartijn agentx_log_axg_warnx(axv->axv_axg,
379881180db9Smartijn "invalid oid length on explicit length "
379981180db9Smartijn "oid");
380081180db9Smartijn agentx_varbind_error_type(axv,
380181180db9Smartijn AX_PDU_ERROR_GENERR, 0);
380281180db9Smartijn return;
380381180db9Smartijn #endif
380481180db9Smartijn }
380581180db9Smartijn curvalue = &(axv->axv_index[i].axv_idata.avb_oid);
38069c70cf54Smartijn if (agentx_oidfill(&oid, value,
38079c70cf54Smartijn oidlen, &errstr) == -1) {
38089c70cf54Smartijn #ifdef AX_DEBUG
38099c70cf54Smartijn agentx_log_axg_fatalx(axv->axv_axg, "%s: %s",
38109c70cf54Smartijn __func__, errstr);
38119c70cf54Smartijn #else
38129c70cf54Smartijn agentx_log_axg_warnx(axv->axv_axg, "%s: %s",
38139c70cf54Smartijn __func__, errstr);
38149c70cf54Smartijn agentx_varbind_error_type(axv,
38159c70cf54Smartijn AX_PDU_ERROR_PROCESSINGERROR, 1);
38169c70cf54Smartijn return;
38179c70cf54Smartijn #endif
38189c70cf54Smartijn }
38199c70cf54Smartijn
382081180db9Smartijn if (axv->axv_axg->axg_type == AX_PDU_TYPE_GET &&
382181180db9Smartijn ax_oid_cmp(&oid, curvalue) != 0) {
382281180db9Smartijn #ifdef AX_DEBUG
382381180db9Smartijn agentx_log_axg_fatalx(axv->axv_axg,
382481180db9Smartijn "can't change index on GET");
382581180db9Smartijn #else
382681180db9Smartijn agentx_log_axg_warnx(axv->axv_axg,
382781180db9Smartijn "can't change index on GET");
382881180db9Smartijn agentx_varbind_error_type(axv,
382981180db9Smartijn AX_PDU_ERROR_GENERR, 0);
383081180db9Smartijn return;
383181180db9Smartijn #endif
383281180db9Smartijn }
38339c70cf54Smartijn
38349c70cf54Smartijn *curvalue = oid;
383581180db9Smartijn return;
383681180db9Smartijn }
383781180db9Smartijn }
383881180db9Smartijn #ifdef AX_DEBUG
383981180db9Smartijn agentx_log_axg_fatalx(axv->axv_axg, "invalid index");
384081180db9Smartijn #else
384181180db9Smartijn agentx_log_axg_warnx(axv->axv_axg, "invalid index");
384281180db9Smartijn agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
384381180db9Smartijn #endif
384481180db9Smartijn }
384581180db9Smartijn
384681180db9Smartijn void
384781180db9Smartijn agentx_varbind_set_index_object(struct agentx_varbind *axv,
384881180db9Smartijn struct agentx_index *axi, struct agentx_object *axo)
384981180db9Smartijn {
385081180db9Smartijn agentx_varbind_set_index_oid(axv, axi, axo->axo_oid.aoi_id,
385181180db9Smartijn axo->axo_oid.aoi_idlen);
385281180db9Smartijn }
385381180db9Smartijn
385481180db9Smartijn void
385581180db9Smartijn agentx_varbind_set_index_ipaddress(struct agentx_varbind *axv,
385681180db9Smartijn struct agentx_index *axi, const struct in_addr *addr)
385781180db9Smartijn {
385881180db9Smartijn struct ax_ostring *curvalue;
385981180db9Smartijn size_t i;
386081180db9Smartijn
386181180db9Smartijn if (axi->axi_vb.avb_type != AX_DATA_TYPE_IPADDRESS) {
386281180db9Smartijn #ifdef AX_DEBUG
386381180db9Smartijn agentx_log_axg_fatalx(axv->axv_axg, "invalid index type");
386481180db9Smartijn #else
386581180db9Smartijn agentx_log_axg_warnx(axv->axv_axg, "invalid index type");
386681180db9Smartijn agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
386781180db9Smartijn return;
386881180db9Smartijn #endif
386981180db9Smartijn }
387081180db9Smartijn
387181180db9Smartijn for (i = 0; i < axv->axv_indexlen; i++) {
387281180db9Smartijn if (axv->axv_index[i].axv_axi == axi) {
387381180db9Smartijn curvalue = &(axv->axv_index[i].axv_idata.avb_ostring);
387481180db9Smartijn if (curvalue->aos_string == NULL)
387581180db9Smartijn curvalue->aos_string = calloc(1, sizeof(*addr));
387681180db9Smartijn if (curvalue->aos_string == NULL) {
387781180db9Smartijn agentx_log_axg_warn(axv->axv_axg,
387881180db9Smartijn "Failed to bind ipaddress index");
387981180db9Smartijn agentx_varbind_error_type(axv,
388081180db9Smartijn AX_PDU_ERROR_PROCESSINGERROR, 0);
388181180db9Smartijn return;
388281180db9Smartijn }
388381180db9Smartijn if (axv->axv_axg->axg_type == AX_PDU_TYPE_GET &&
388481180db9Smartijn memcmp(addr, curvalue->aos_string,
388581180db9Smartijn sizeof(*addr)) != 0) {
388681180db9Smartijn #ifdef AX_DEBUG
388781180db9Smartijn agentx_log_axg_fatalx(axv->axv_axg,
388881180db9Smartijn "can't change index on GET");
388981180db9Smartijn #else
389081180db9Smartijn agentx_log_axg_warnx(axv->axv_axg,
389181180db9Smartijn "can't change index on GET");
389281180db9Smartijn agentx_varbind_error_type(axv,
389381180db9Smartijn AX_PDU_ERROR_GENERR, 0);
389481180db9Smartijn return;
389581180db9Smartijn #endif
389681180db9Smartijn }
389781180db9Smartijn bcopy(addr, curvalue->aos_string, sizeof(*addr));
389881180db9Smartijn return;
389981180db9Smartijn }
390081180db9Smartijn }
390181180db9Smartijn #ifdef AX_DEBUG
390281180db9Smartijn agentx_log_axg_fatalx(axv->axv_axg, "invalid index");
390381180db9Smartijn #else
390481180db9Smartijn agentx_log_axg_warnx(axv->axv_axg, "invalid index");
390581180db9Smartijn agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
390681180db9Smartijn #endif
390781180db9Smartijn }
390881180db9Smartijn
390981180db9Smartijn static int
391081180db9Smartijn agentx_request(struct agentx *ax, uint32_t packetid,
391181180db9Smartijn int (*cb)(struct ax_pdu *, void *), void *cookie)
391281180db9Smartijn {
391381180db9Smartijn struct agentx_request *axr;
391481180db9Smartijn
391581180db9Smartijn #ifdef AX_DEBUG
391681180db9Smartijn if (ax->ax_ax->ax_wblen == 0)
391781180db9Smartijn agentx_log_ax_fatalx(ax, "%s: no data to be written",
391881180db9Smartijn __func__);
391981180db9Smartijn #endif
392081180db9Smartijn
392181180db9Smartijn if ((axr = calloc(1, sizeof(*axr))) == NULL) {
392281180db9Smartijn agentx_log_ax_warn(ax, "couldn't create request context");
392381180db9Smartijn agentx_reset(ax);
39249dbe2cd1Smartijn return -1;
39259dbe2cd1Smartijn }
392681180db9Smartijn
392781180db9Smartijn axr->axr_packetid = packetid;
392881180db9Smartijn axr->axr_cb = cb;
392981180db9Smartijn axr->axr_cookie = cookie;
393081180db9Smartijn if (RB_INSERT(ax_requests, &(ax->ax_requests), axr) != NULL) {
393181180db9Smartijn #ifdef AX_DEBUG
393281180db9Smartijn agentx_log_ax_fatalx(ax, "%s: duplicate packetid", __func__);
393381180db9Smartijn #else
393481180db9Smartijn agentx_log_ax_warnx(ax, "%s: duplicate packetid", __func__);
393581180db9Smartijn free(axr);
393681180db9Smartijn agentx_reset(ax);
393781180db9Smartijn return -1;
393881180db9Smartijn #endif
393981180db9Smartijn }
394081180db9Smartijn
394181180db9Smartijn agentx_wantwrite(ax, ax->ax_fd);
394281180db9Smartijn return 0;
394381180db9Smartijn }
394481180db9Smartijn
394581180db9Smartijn static int
394681180db9Smartijn agentx_request_cmp(struct agentx_request *r1,
394781180db9Smartijn struct agentx_request *r2)
394881180db9Smartijn {
394981180db9Smartijn return r1->axr_packetid < r2->axr_packetid ? -1 :
395081180db9Smartijn r1->axr_packetid > r2->axr_packetid;
395181180db9Smartijn }
395281180db9Smartijn
395381180db9Smartijn static int
395481180db9Smartijn agentx_strcat(char **dst, const char *src)
395581180db9Smartijn {
395681180db9Smartijn char *tmp;
395781180db9Smartijn size_t dstlen = 0, buflen = 0, srclen, nbuflen;
395881180db9Smartijn
395981180db9Smartijn if (*dst != NULL) {
396081180db9Smartijn dstlen = strlen(*dst);
396181180db9Smartijn buflen = ((dstlen / 512) + 1) * 512;
396281180db9Smartijn }
396381180db9Smartijn
396481180db9Smartijn srclen = strlen(src);
396581180db9Smartijn if (*dst == NULL || dstlen + srclen > buflen) {
396681180db9Smartijn nbuflen = (((dstlen + srclen) / 512) + 1) * 512;
396781180db9Smartijn tmp = recallocarray(*dst, buflen, nbuflen, sizeof(*tmp));
396881180db9Smartijn if (tmp == NULL)
396981180db9Smartijn return -1;
397081180db9Smartijn *dst = tmp;
397181180db9Smartijn buflen = nbuflen;
397281180db9Smartijn }
397381180db9Smartijn
397481180db9Smartijn (void)strlcat(*dst, src, buflen);
397581180db9Smartijn return 0;
397681180db9Smartijn }
397781180db9Smartijn
39789c70cf54Smartijn static int
39799c70cf54Smartijn agentx_oidfill(struct ax_oid *oid, const uint32_t oidval[], size_t oidlen,
39809c70cf54Smartijn const char **errstr)
39819c70cf54Smartijn {
39829c70cf54Smartijn size_t i;
39839c70cf54Smartijn
39849c70cf54Smartijn if (oidlen < AGENTX_OID_MIN_LEN) {
39859c70cf54Smartijn *errstr = "oidlen < 2";
39869c70cf54Smartijn errno = EINVAL;
39879c70cf54Smartijn return -1;
39889c70cf54Smartijn }
39899c70cf54Smartijn if (oidlen > AGENTX_OID_MAX_LEN) {
39909c70cf54Smartijn *errstr = "oidlen > 128";
39919c70cf54Smartijn errno = EINVAL;
39929c70cf54Smartijn return -1;
39939c70cf54Smartijn }
39949c70cf54Smartijn
39959c70cf54Smartijn for (i = 0; i < oidlen; i++)
39969c70cf54Smartijn oid->aoi_id[i] = oidval[i];
39979c70cf54Smartijn oid->aoi_idlen = oidlen;
39989c70cf54Smartijn return 0;
39999c70cf54Smartijn }
40009c70cf54Smartijn
400181180db9Smartijn void
400281180db9Smartijn agentx_read(struct agentx *ax)
400381180db9Smartijn {
400481180db9Smartijn struct agentx_session *axs;
400581180db9Smartijn struct agentx_context *axc;
400681180db9Smartijn struct agentx_request axr_search, *axr;
400781180db9Smartijn struct ax_pdu *pdu;
400881180db9Smartijn int error;
400981180db9Smartijn
401081180db9Smartijn if ((pdu = ax_recv(ax->ax_ax)) == NULL) {
401181180db9Smartijn if (errno == EAGAIN)
401281180db9Smartijn return;
401381180db9Smartijn agentx_log_ax_warn(ax, "lost connection");
401481180db9Smartijn agentx_reset(ax);
401581180db9Smartijn return;
401681180db9Smartijn }
401781180db9Smartijn
401881180db9Smartijn TAILQ_FOREACH(axs, &(ax->ax_sessions), axs_ax_sessions) {
401981180db9Smartijn if (axs->axs_id == pdu->ap_header.aph_sessionid)
402081180db9Smartijn break;
402181180db9Smartijn if (axs->axs_cstate == AX_CSTATE_WAITOPEN &&
402281180db9Smartijn axs->axs_packetid == pdu->ap_header.aph_packetid)
402381180db9Smartijn break;
402481180db9Smartijn }
402581180db9Smartijn if (axs == NULL) {
402681180db9Smartijn agentx_log_ax_warnx(ax, "received unexpected session: %d",
402781180db9Smartijn pdu->ap_header.aph_sessionid);
402881180db9Smartijn ax_pdu_free(pdu);
402981180db9Smartijn agentx_reset(ax);
403081180db9Smartijn return;
403181180db9Smartijn }
403281180db9Smartijn TAILQ_FOREACH(axc, &(axs->axs_contexts), axc_axs_contexts) {
403381180db9Smartijn if ((pdu->ap_header.aph_flags &
403481180db9Smartijn AX_PDU_FLAG_NON_DEFAULT_CONTEXT) == 0 &&
403581180db9Smartijn axc->axc_name_default == 1)
403681180db9Smartijn break;
403781180db9Smartijn if (pdu->ap_header.aph_flags &
403881180db9Smartijn AX_PDU_FLAG_NON_DEFAULT_CONTEXT &&
403981180db9Smartijn axc->axc_name_default == 0 &&
404081180db9Smartijn pdu->ap_context.aos_slen == axc->axc_name.aos_slen &&
404181180db9Smartijn memcmp(pdu->ap_context.aos_string,
404281180db9Smartijn axc->axc_name.aos_string, axc->axc_name.aos_slen) == 0)
404381180db9Smartijn break;
404481180db9Smartijn }
404581180db9Smartijn if (pdu->ap_header.aph_type != AX_PDU_TYPE_RESPONSE) {
404681180db9Smartijn if (axc == NULL) {
404781180db9Smartijn agentx_log_ax_warnx(ax, "%s: invalid context",
404881180db9Smartijn pdu->ap_context.aos_string);
404981180db9Smartijn ax_pdu_free(pdu);
405081180db9Smartijn agentx_reset(ax);
405181180db9Smartijn return;
405281180db9Smartijn }
405381180db9Smartijn }
405481180db9Smartijn
405581180db9Smartijn switch (pdu->ap_header.aph_type) {
405681180db9Smartijn case AX_PDU_TYPE_GET:
405781180db9Smartijn case AX_PDU_TYPE_GETNEXT:
405881180db9Smartijn case AX_PDU_TYPE_GETBULK:
405981180db9Smartijn agentx_get_start(axc, pdu);
406081180db9Smartijn break;
406181180db9Smartijn /* Add stubs for set functions */
406281180db9Smartijn case AX_PDU_TYPE_TESTSET:
406381180db9Smartijn case AX_PDU_TYPE_COMMITSET:
406481180db9Smartijn case AX_PDU_TYPE_UNDOSET:
406581180db9Smartijn if (pdu->ap_header.aph_type == AX_PDU_TYPE_TESTSET)
406681180db9Smartijn error = AX_PDU_ERROR_NOTWRITABLE;
406781180db9Smartijn else if (pdu->ap_header.aph_type == AX_PDU_TYPE_COMMITSET)
406881180db9Smartijn error = AX_PDU_ERROR_COMMITFAILED;
406981180db9Smartijn else
407081180db9Smartijn error = AX_PDU_ERROR_UNDOFAILED;
407181180db9Smartijn
407281180db9Smartijn agentx_log_axc_debug(axc, "unsupported call: %s",
407381180db9Smartijn ax_pdutype2string(pdu->ap_header.aph_type));
407481180db9Smartijn if (ax_response(ax->ax_ax, axs->axs_id,
407581180db9Smartijn pdu->ap_header.aph_transactionid,
407681180db9Smartijn pdu->ap_header.aph_packetid,
407781180db9Smartijn 0, error, 1, NULL, 0) == -1)
407881180db9Smartijn agentx_log_axc_warn(axc,
407981180db9Smartijn "transaction: %u packetid: %u: failed to send "
408081180db9Smartijn "reply", pdu->ap_header.aph_transactionid,
408181180db9Smartijn pdu->ap_header.aph_packetid);
408281180db9Smartijn if (ax->ax_ax->ax_wblen > 0)
408381180db9Smartijn agentx_wantwrite(ax, ax->ax_fd);
408481180db9Smartijn break;
408581180db9Smartijn case AX_PDU_TYPE_CLEANUPSET:
408681180db9Smartijn agentx_log_ax_debug(ax, "unsupported call: %s",
408781180db9Smartijn ax_pdutype2string(pdu->ap_header.aph_type));
408881180db9Smartijn break;
408981180db9Smartijn case AX_PDU_TYPE_RESPONSE:
409081180db9Smartijn axr_search.axr_packetid = pdu->ap_header.aph_packetid;
409181180db9Smartijn axr = RB_FIND(ax_requests, &(ax->ax_requests), &axr_search);
409281180db9Smartijn if (axr == NULL) {
409381180db9Smartijn if (axc == NULL)
409481180db9Smartijn agentx_log_ax_warnx(ax, "received "
409581180db9Smartijn "response on non-request");
409681180db9Smartijn else
409781180db9Smartijn agentx_log_axc_warnx(axc, "received "
409881180db9Smartijn "response on non-request");
409981180db9Smartijn break;
410081180db9Smartijn }
410181180db9Smartijn if (axc != NULL && pdu->ap_payload.ap_response.ap_error == 0) {
410281180db9Smartijn axc->axc_sysuptime =
410381180db9Smartijn pdu->ap_payload.ap_response.ap_uptime;
410481180db9Smartijn (void) clock_gettime(CLOCK_MONOTONIC,
410581180db9Smartijn &(axc->axc_sysuptimespec));
410681180db9Smartijn }
410781180db9Smartijn RB_REMOVE(ax_requests, &(ax->ax_requests), axr);
410881180db9Smartijn (void) axr->axr_cb(pdu, axr->axr_cookie);
410981180db9Smartijn free(axr);
411081180db9Smartijn break;
411181180db9Smartijn default:
411281180db9Smartijn if (axc == NULL)
411381180db9Smartijn agentx_log_ax_warnx(ax, "unsupported call: %s",
411481180db9Smartijn ax_pdutype2string(pdu->ap_header.aph_type));
411581180db9Smartijn else
411681180db9Smartijn agentx_log_axc_warnx(axc, "unsupported call: %s",
411781180db9Smartijn ax_pdutype2string(pdu->ap_header.aph_type));
411881180db9Smartijn agentx_reset(ax);
411981180db9Smartijn break;
412081180db9Smartijn }
412181180db9Smartijn ax_pdu_free(pdu);
412281180db9Smartijn }
412381180db9Smartijn
412481180db9Smartijn void
412581180db9Smartijn agentx_write(struct agentx *ax)
412681180db9Smartijn {
412781180db9Smartijn ssize_t send;
412881180db9Smartijn
412981180db9Smartijn if ((send = ax_send(ax->ax_ax)) == -1) {
413081180db9Smartijn if (errno == EAGAIN) {
413181180db9Smartijn agentx_wantwrite(ax, ax->ax_fd);
413281180db9Smartijn return;
413381180db9Smartijn }
413481180db9Smartijn agentx_log_ax_warn(ax, "lost connection");
413581180db9Smartijn agentx_reset(ax);
413681180db9Smartijn return;
413781180db9Smartijn }
413881180db9Smartijn if (send > 0)
413981180db9Smartijn agentx_wantwrite(ax, ax->ax_fd);
414081180db9Smartijn }
414181180db9Smartijn
414281180db9Smartijn RB_GENERATE_STATIC(ax_requests, agentx_request, axr_ax_requests,
414381180db9Smartijn agentx_request_cmp)
414481180db9Smartijn RB_GENERATE_STATIC(axc_objects, agentx_object, axo_axc_objects,
414581180db9Smartijn agentx_object_cmp)
4146