Bug Summary

File:src/lib/libagentx/agentx.c
Warning:line 3875, column 28
Result of 'calloc' is converted to a pointer of type 'unsigned char', which is incompatible with sizeof operand type 'const struct in_addr'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name agentx.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/lib/libagentx/obj -resource-dir /usr/local/llvm16/lib/clang/16 -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/lib/libagentx/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/lib/libagentx/agentx.c
1/* $OpenBSD: agentx.c,v 1.24 2023/10/29 11:10:07 martijn Exp $ */
2/*
3 * Copyright (c) 2019 Martijn van Duren <martijn@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17#include <netinet/in.h>
18
19#include <errno(*__errno()).h>
20#include <stdarg.h>
21#include <stdlib.h>
22#include <stdio.h>
23#include <string.h>
24#include <strings.h>
25#include <time.h>
26#include <unistd.h>
27
28#include "agentx_internal.h"
29#include <agentx.h>
30
31/*
32 * ax: struct agentx
33 * axs: struct agentx_session
34 * axc: struct agentx_context
35 * axr: struct agentx_region
36 * axi: struct agentx_index
37 * axo: struct agentx_object
38 * axg: struct agentx_get
39 * axv: struct agentx_varbind
40 * axr: struct agentx_request
41 * cstate: current state
42 * dstate: desired state
43 */
44
45enum agentx_index_type {
46 AXI_TYPE_NEW,
47 AXI_TYPE_ANY,
48 AXI_TYPE_VALUE,
49 AXI_TYPE_DYNAMIC
50};
51
52#define AGENTX_CONTEXT_CTX(axc)(axc->axc_name_default ? ((void *)0) : &(axc->axc_name
))
(axc->axc_name_default ? NULL((void *)0) : \
53 &(axc->axc_name))
54
55struct agentx_agentcaps {
56 struct agentx_context *axa_axc;
57 struct ax_oid axa_oid;
58 struct ax_ostring axa_descr;
59 enum agentx_cstate axa_cstate;
60 enum agentx_dstate axa_dstate;
61 TAILQ_ENTRY(agentx_agentcaps)struct { struct agentx_agentcaps *tqe_next; struct agentx_agentcaps
**tqe_prev; }
axa_axc_agentcaps;
62};
63
64struct agentx_region {
65 struct agentx_context *axr_axc;
66 struct ax_oid axr_oid;
67 uint8_t axr_timeout;
68 uint8_t axr_priority;
69 enum agentx_cstate axr_cstate;
70 enum agentx_dstate axr_dstate;
71 TAILQ_HEAD(, agentx_index)struct { struct agentx_index *tqh_first; struct agentx_index *
*tqh_last; }
axr_indices;
72 TAILQ_HEAD(, agentx_object)struct { struct agentx_object *tqh_first; struct agentx_object
**tqh_last; }
axr_objects;
73 TAILQ_ENTRY(agentx_region)struct { struct agentx_region *tqe_next; struct agentx_region
**tqe_prev; }
axr_axc_regions;
74};
75
76struct agentx_index {
77 struct agentx_region *axi_axr;
78 enum agentx_index_type axi_type;
79 struct ax_varbind axi_vb;
80 struct agentx_object **axi_object;
81 size_t axi_objectlen;
82 size_t axi_objectsize;
83 enum agentx_cstate axi_cstate;
84 enum agentx_dstate axi_dstate;
85 TAILQ_ENTRY(agentx_index)struct { struct agentx_index *tqe_next; struct agentx_index *
*tqe_prev; }
axi_axr_indices;
86};
87
88struct agentx_object {
89 struct agentx_region *axo_axr;
90 struct ax_oid axo_oid;
91 struct agentx_index *axo_index[AGENTX_OID_INDEX_MAX_LEN10];
92 size_t axo_indexlen;
93 int axo_implied;
94 uint8_t axo_timeout;
95 /* Prevent freeing object while in use by get and set requesets */
96 uint32_t axo_lock;
97 void (*axo_get)(struct agentx_varbind *);
98 enum agentx_cstate axo_cstate;
99 enum agentx_dstate axo_dstate;
100 RB_ENTRY(agentx_object)struct { struct agentx_object *rbe_left; struct agentx_object
*rbe_right; struct agentx_object *rbe_parent; int rbe_color;
}
axo_axc_objects;
101 TAILQ_ENTRY(agentx_object)struct { struct agentx_object *tqe_next; struct agentx_object
**tqe_prev; }
axo_axr_objects;
102};
103
104struct agentx_varbind {
105 struct agentx_get *axv_axg;
106 struct agentx_object *axv_axo;
107 struct agentx_varbind_index {
108 struct agentx_index *axv_axi;
109 union ax_data axv_idata;
110 } axv_index[AGENTX_OID_INDEX_MAX_LEN10];
111 size_t axv_indexlen;
112 int axv_initialized;
113 int axv_include;
114 struct ax_varbind axv_vb;
115 struct ax_oid axv_start;
116 struct ax_oid axv_end;
117 enum ax_pdu_error axv_error;
118};
119
120#define AGENTX_GET_CTX(axg)(axg->axg_context_default ? ((void *)0) : &(axg->axg_context
))
(axg->axg_context_default ? NULL((void *)0) : \
121 &(axg->axg_context))
122struct agentx_request {
123 uint32_t axr_packetid;
124 int (*axr_cb)(struct ax_pdu *, void *);
125 void *axr_cookie;
126 RB_ENTRY(agentx_request)struct { struct agentx_request *rbe_left; struct agentx_request
*rbe_right; struct agentx_request *rbe_parent; int rbe_color
; }
axr_ax_requests;
127};
128
129static void agentx_start(struct agentx *);
130static void agentx_finalize(struct agentx *, int);
131static void agentx_wantwritenow(struct agentx *, int);
132void (*agentx_wantwrite)(struct agentx *, int) =
133 agentx_wantwritenow;
134static void agentx_reset(struct agentx *);
135static void agentx_free_finalize(struct agentx *);
136static int agentx_session_retry(struct agentx_session *);
137static int agentx_session_start(struct agentx_session *);
138static int agentx_session_finalize(struct ax_pdu *, void *);
139static int agentx_session_close(struct agentx_session *,
140 enum ax_close_reason);
141static int agentx_session_close_finalize(struct ax_pdu *, void *);
142static void agentx_session_free_finalize(struct agentx_session *);
143static void agentx_session_reset(struct agentx_session *);
144static int agentx_context_retry(struct agentx_context *);
145static void agentx_context_start(struct agentx_context *);
146static void agentx_context_free_finalize(struct agentx_context *);
147static void agentx_context_reset(struct agentx_context *);
148static int agentx_agentcaps_start(struct agentx_agentcaps *);
149static int agentx_agentcaps_finalize(struct ax_pdu *, void *);
150static int agentx_agentcaps_close(struct agentx_agentcaps *);
151static int agentx_agentcaps_close_finalize(struct ax_pdu *, void *);
152static void agentx_agentcaps_free_finalize(struct agentx_agentcaps *);
153static void agentx_agentcaps_reset(struct agentx_agentcaps *);
154static int agentx_region_retry(struct agentx_region *);
155static int agentx_region_start(struct agentx_region *);
156static int agentx_region_finalize(struct ax_pdu *, void *);
157static int agentx_region_close(struct agentx_region *);
158static int agentx_region_close_finalize(struct ax_pdu *, void *);
159static void agentx_region_free_finalize(struct agentx_region *);
160static void agentx_region_reset(struct agentx_region *);
161static struct agentx_index *agentx_index(struct agentx_region *,
162 struct ax_varbind *, enum agentx_index_type);
163static int agentx_index_start(struct agentx_index *);
164static int agentx_index_finalize(struct ax_pdu *, void *);
165static void agentx_index_free_finalize(struct agentx_index *);
166static void agentx_index_reset(struct agentx_index *);
167static int agentx_index_close(struct agentx_index *);
168static int agentx_index_close_finalize(struct ax_pdu *, void *);
169static int agentx_object_start(struct agentx_object *);
170static int agentx_object_finalize(struct ax_pdu *, void *);
171static int agentx_object_lock(struct agentx_object *);
172static void agentx_object_unlock(struct agentx_object *);
173static int agentx_object_close(struct agentx_object *);
174static int agentx_object_close_finalize(struct ax_pdu *, void *);
175static void agentx_object_free_finalize(struct agentx_object *);
176static void agentx_object_reset(struct agentx_object *);
177static int agentx_object_cmp(struct agentx_object *,
178 struct agentx_object *);
179static void agentx_get_start(struct agentx_context *,
180 struct ax_pdu *);
181static void agentx_get_finalize(struct agentx_get *);
182static void agentx_get_free(struct agentx_get *);
183static void agentx_varbind_start(struct agentx_varbind *);
184static void agentx_varbind_finalize(struct agentx_varbind *);
185static void agentx_varbind_nosuchobject(struct agentx_varbind *);
186static void agentx_varbind_nosuchinstance(struct agentx_varbind *);
187static void agentx_varbind_endofmibview(struct agentx_varbind *);
188static void agentx_varbind_error_type(struct agentx_varbind *,
189 enum ax_pdu_error, int);
190static int agentx_request(struct agentx *, uint32_t,
191 int (*)(struct ax_pdu *, void *), void *);
192static int agentx_request_cmp(struct agentx_request *,
193 struct agentx_request *);
194static int agentx_strcat(char **, const char *);
195static int agentx_oidfill(struct ax_oid *, const uint32_t[], size_t,
196 const char **);
197
198RB_PROTOTYPE_STATIC(ax_requests, agentx_request, axr_ax_requests,__attribute__((__unused__)) static void ax_requests_RB_INSERT_COLOR
(struct ax_requests *, struct agentx_request *); __attribute__
((__unused__)) static void ax_requests_RB_REMOVE_COLOR(struct
ax_requests *, struct agentx_request *, struct agentx_request
*);__attribute__((__unused__)) static struct agentx_request *
ax_requests_RB_REMOVE(struct ax_requests *, struct agentx_request
*); __attribute__((__unused__)) static struct agentx_request
*ax_requests_RB_INSERT(struct ax_requests *, struct agentx_request
*); __attribute__((__unused__)) static struct agentx_request
*ax_requests_RB_FIND(struct ax_requests *, struct agentx_request
*); __attribute__((__unused__)) static struct agentx_request
*ax_requests_RB_NFIND(struct ax_requests *, struct agentx_request
*); __attribute__((__unused__)) static struct agentx_request
*ax_requests_RB_NEXT(struct agentx_request *); __attribute__
((__unused__)) static struct agentx_request *ax_requests_RB_PREV
(struct agentx_request *); __attribute__((__unused__)) static
struct agentx_request *ax_requests_RB_MINMAX(struct ax_requests
*, int);
199 agentx_request_cmp)__attribute__((__unused__)) static void ax_requests_RB_INSERT_COLOR
(struct ax_requests *, struct agentx_request *); __attribute__
((__unused__)) static void ax_requests_RB_REMOVE_COLOR(struct
ax_requests *, struct agentx_request *, struct agentx_request
*);__attribute__((__unused__)) static struct agentx_request *
ax_requests_RB_REMOVE(struct ax_requests *, struct agentx_request
*); __attribute__((__unused__)) static struct agentx_request
*ax_requests_RB_INSERT(struct ax_requests *, struct agentx_request
*); __attribute__((__unused__)) static struct agentx_request
*ax_requests_RB_FIND(struct ax_requests *, struct agentx_request
*); __attribute__((__unused__)) static struct agentx_request
*ax_requests_RB_NFIND(struct ax_requests *, struct agentx_request
*); __attribute__((__unused__)) static struct agentx_request
*ax_requests_RB_NEXT(struct agentx_request *); __attribute__
((__unused__)) static struct agentx_request *ax_requests_RB_PREV
(struct agentx_request *); __attribute__((__unused__)) static
struct agentx_request *ax_requests_RB_MINMAX(struct ax_requests
*, int);
200RB_PROTOTYPE_STATIC(axc_objects, agentx_object, axo_axc_objects,__attribute__((__unused__)) static void axc_objects_RB_INSERT_COLOR
(struct axc_objects *, struct agentx_object *); __attribute__
((__unused__)) static void axc_objects_RB_REMOVE_COLOR(struct
axc_objects *, struct agentx_object *, struct agentx_object *
);__attribute__((__unused__)) static struct agentx_object *axc_objects_RB_REMOVE
(struct axc_objects *, struct agentx_object *); __attribute__
((__unused__)) static struct agentx_object *axc_objects_RB_INSERT
(struct axc_objects *, struct agentx_object *); __attribute__
((__unused__)) static struct agentx_object *axc_objects_RB_FIND
(struct axc_objects *, struct agentx_object *); __attribute__
((__unused__)) static struct agentx_object *axc_objects_RB_NFIND
(struct axc_objects *, struct agentx_object *); __attribute__
((__unused__)) static struct agentx_object *axc_objects_RB_NEXT
(struct agentx_object *); __attribute__((__unused__)) static struct
agentx_object *axc_objects_RB_PREV(struct agentx_object *); __attribute__
((__unused__)) static struct agentx_object *axc_objects_RB_MINMAX
(struct axc_objects *, int);
201 agentx_object_cmp)__attribute__((__unused__)) static void axc_objects_RB_INSERT_COLOR
(struct axc_objects *, struct agentx_object *); __attribute__
((__unused__)) static void axc_objects_RB_REMOVE_COLOR(struct
axc_objects *, struct agentx_object *, struct agentx_object *
);__attribute__((__unused__)) static struct agentx_object *axc_objects_RB_REMOVE
(struct axc_objects *, struct agentx_object *); __attribute__
((__unused__)) static struct agentx_object *axc_objects_RB_INSERT
(struct axc_objects *, struct agentx_object *); __attribute__
((__unused__)) static struct agentx_object *axc_objects_RB_FIND
(struct axc_objects *, struct agentx_object *); __attribute__
((__unused__)) static struct agentx_object *axc_objects_RB_NFIND
(struct axc_objects *, struct agentx_object *); __attribute__
((__unused__)) static struct agentx_object *axc_objects_RB_NEXT
(struct agentx_object *); __attribute__((__unused__)) static struct
agentx_object *axc_objects_RB_PREV(struct agentx_object *); __attribute__
((__unused__)) static struct agentx_object *axc_objects_RB_MINMAX
(struct axc_objects *, int);
202
203struct agentx *
204agentx(void (*nofd)(struct agentx *, void *, int), void *cookie)
205{
206 struct agentx *ax;
207
208 if ((ax = calloc(1, sizeof(*ax))) == NULL((void *)0))
209 return NULL((void *)0);
210
211 ax->ax_nofd = nofd;
212 ax->ax_cookie = cookie;
213 ax->ax_fd = -1;
214 ax->ax_cstate = AX_CSTATE_CLOSE;
215 ax->ax_dstate = AX_DSTATE_OPEN;
216 TAILQ_INIT(&(ax->ax_sessions))do { (&(ax->ax_sessions))->tqh_first = ((void *)0);
(&(ax->ax_sessions))->tqh_last = &(&(ax->
ax_sessions))->tqh_first; } while (0)
;
217 TAILQ_INIT(&(ax->ax_getreqs))do { (&(ax->ax_getreqs))->tqh_first = ((void *)0); (
&(ax->ax_getreqs))->tqh_last = &(&(ax->ax_getreqs
))->tqh_first; } while (0)
;
218 RB_INIT(&(ax->ax_requests))do { (&(ax->ax_requests))->rbh_root = ((void *)0); }
while (0)
;
219
220 agentx_start(ax);
221
222 return ax;
223}
224
225/*
226 * agentx_finalize is not a suitable name for a public API,
227 * but use it internally for consistency
228 */
229void
230agentx_connect(struct agentx *ax, int fd)
231{
232 agentx_finalize(ax, fd);
233}
234
235void
236agentx_retry(struct agentx *ax)
237{
238 struct agentx_session *axs;
239
240 if (ax->ax_fd == -1)
241 return;
242
243 TAILQ_FOREACH(axs, &(ax->ax_sessions), axs_ax_sessions)for((axs) = ((&(ax->ax_sessions))->tqh_first); (axs
) != ((void *)0); (axs) = ((axs)->axs_ax_sessions.tqe_next
))
{
244 if (axs->axs_cstate == AX_CSTATE_OPEN) {
245 if (agentx_session_retry(axs) == -1)
246 return;
247 } else if (axs->axs_cstate == AX_CSTATE_CLOSE) {
248 if (agentx_session_start(axs) == -1)
249 return;
250 }
251 }
252}
253
254static void
255agentx_start(struct agentx *ax)
256{
257#ifdef AX_DEBUG
258 if (ax->ax_cstate != AX_CSTATE_CLOSE ||
259 ax->ax_dstate != AX_DSTATE_OPEN)
260 agentx_log_ax_fatalx(ax, "%s: unexpected connect", __func__);
261#endif
262 ax->ax_cstate = AX_CSTATE_WAITOPEN;
263 ax->ax_nofd(ax, ax->ax_cookie, 0);
264}
265
266static void
267agentx_finalize(struct agentx *ax, int fd)
268{
269 struct agentx_session *axs;
270
271 if (ax->ax_cstate != AX_CSTATE_WAITOPEN) {
272#ifdef AX_DEBUG
273 agentx_log_ax_fatalx(ax, "%s: agentx unexpected connect",
274 __func__);
275#else
276 agentx_log_ax_warnx(ax,
277 "%s: agentx unexpected connect: ignoring", __func__);
278 return;
279#endif
280 }
281 if ((ax->ax_ax = ax_new(fd)) == NULL((void *)0)) {
282 agentx_log_ax_warn(ax, "failed to initialize");
283 close(fd);
284 agentx_reset(ax);
285 return;
286 }
287
288 agentx_log_ax_info(ax, "new connection: %d", fd);
289
290 ax->ax_fd = fd;
291 ax->ax_cstate = AX_CSTATE_OPEN;
292
293 TAILQ_FOREACH(axs, &(ax->ax_sessions), axs_ax_sessions)for((axs) = ((&(ax->ax_sessions))->tqh_first); (axs
) != ((void *)0); (axs) = ((axs)->axs_ax_sessions.tqe_next
))
{
294 if (agentx_session_start(axs) == -1)
295 break;
296 }
297}
298
299static void
300agentx_wantwritenow(struct agentx *ax, int fd)
301{
302 agentx_write(ax);
303}
304
305static void
306agentx_reset(struct agentx *ax)
307{
308 struct agentx_session *axs, *taxs;
309 struct agentx_request *axr;
310 struct agentx_get *axg;
311 int axfree = ax->ax_free;
312
313 ax_free(ax->ax_ax);
314 ax->ax_ax = NULL((void *)0);
315 ax->ax_fd = -1;
316 ax->ax_free = 1;
317
318 ax->ax_cstate = AX_CSTATE_CLOSE;
319
320 while ((axr = RB_MIN(ax_requests, &(ax->ax_requests))ax_requests_RB_MINMAX(&(ax->ax_requests), -1)) != NULL((void *)0)) {
321 RB_REMOVE(ax_requests, &(ax->ax_requests), axr)ax_requests_RB_REMOVE(&(ax->ax_requests), axr);
322 free(axr);
323 }
324 TAILQ_FOREACH_SAFE(axs, &(ax->ax_sessions), axs_ax_sessions, taxs)for ((axs) = ((&(ax->ax_sessions))->tqh_first); (axs
) != ((void *)0) && ((taxs) = ((axs)->axs_ax_sessions
.tqe_next), 1); (axs) = (taxs))
325 agentx_session_reset(axs);
326 while (!TAILQ_EMPTY(&(ax->ax_getreqs))(((&(ax->ax_getreqs))->tqh_first) == ((void *)0))) {
327 axg = TAILQ_FIRST(&(ax->ax_getreqs))((&(ax->ax_getreqs))->tqh_first);
328 axg->axg_axc = NULL((void *)0);
329 TAILQ_REMOVE(&(ax->ax_getreqs), axg, axg_ax_getreqs)do { if (((axg)->axg_ax_getreqs.tqe_next) != ((void *)0)) (
axg)->axg_ax_getreqs.tqe_next->axg_ax_getreqs.tqe_prev =
(axg)->axg_ax_getreqs.tqe_prev; else (&(ax->ax_getreqs
))->tqh_last = (axg)->axg_ax_getreqs.tqe_prev; *(axg)->
axg_ax_getreqs.tqe_prev = (axg)->axg_ax_getreqs.tqe_next; ;
; } while (0)
;
330 }
331
332 if (ax->ax_dstate == AX_DSTATE_OPEN)
333 agentx_start(ax);
334
335 if (!axfree)
336 agentx_free_finalize(ax);
337}
338
339void
340agentx_free(struct agentx *ax)
341{
342 struct agentx_session *axs, *taxs;
343 int axfree;
344
345 if (ax == NULL((void *)0))
346 return;
347
348 axfree = ax->ax_free;
349 ax->ax_free = 1;
350
351 /* Malloc throws abort on invalid pointers as well */
352 if (ax->ax_dstate == AX_DSTATE_CLOSE)
353 agentx_log_ax_fatalx(ax, "%s: double free", __func__);
354 ax->ax_dstate = AX_DSTATE_CLOSE;
355
356 TAILQ_FOREACH_SAFE(axs, &(ax->ax_sessions), axs_ax_sessions, taxs)for ((axs) = ((&(ax->ax_sessions))->tqh_first); (axs
) != ((void *)0) && ((taxs) = ((axs)->axs_ax_sessions
.tqe_next), 1); (axs) = (taxs))
{
357 if (axs->axs_dstate != AX_DSTATE_CLOSE)
358 agentx_session_free(axs);
359 }
360 if (!axfree)
361 agentx_free_finalize(ax);
362}
363
364static void
365agentx_free_finalize(struct agentx *ax)
366{
367 struct agentx_session *axs, *taxs;
368
369 ax->ax_free = 0;
370
371 TAILQ_FOREACH_SAFE(axs, &(ax->ax_sessions), axs_ax_sessions, taxs)for ((axs) = ((&(ax->ax_sessions))->tqh_first); (axs
) != ((void *)0) && ((taxs) = ((axs)->axs_ax_sessions
.tqe_next), 1); (axs) = (taxs))
372 agentx_session_free_finalize(axs);
373
374 if (!TAILQ_EMPTY(&(ax->ax_sessions))(((&(ax->ax_sessions))->tqh_first) == ((void *)0)) ||
375 !RB_EMPTY(&(ax->ax_requests))((&(ax->ax_requests))->rbh_root == ((void *)0)) ||
376 ax->ax_dstate != AX_DSTATE_CLOSE)
377 return;
378
379 ax_free(ax->ax_ax);
380 ax->ax_nofd(ax, ax->ax_cookie, 1);
381 free(ax);
382}
383
384struct agentx_session *
385agentx_session(struct agentx *ax, uint32_t oid[],
386 size_t oidlen, const char *descr, uint8_t timeout)
387{
388 struct agentx_session *axs;
389 const char *errstr;
390
391 if ((axs = calloc(1, sizeof(*axs))) == NULL((void *)0))
392 return NULL((void *)0);
393
394 axs->axs_ax = ax;
395 axs->axs_timeout = timeout;
396 /* RFC 2741 section 6.2.1: may send a null Object Identifier */
397 if (oidlen == 0)
398 axs->axs_oid.aoi_idlen = oidlen;
399 else {
400 if (agentx_oidfill((&axs->axs_oid), oid, oidlen,
401 &errstr) == -1) {
402#ifdef AX_DEBUG
403 agentx_log_ax_fatalx(ax, "%s: %s", __func__, errstr);
404#else
405 return NULL((void *)0);
406#endif
407 }
408 }
409 axs->axs_descr.aos_string = (unsigned char *)strdup(descr);
410 if (axs->axs_descr.aos_string == NULL((void *)0)) {
411 free(axs);
412 return NULL((void *)0);
413 }
414 axs->axs_descr.aos_slen = strlen(descr);
415 axs->axs_cstate = AX_CSTATE_CLOSE;
416 axs->axs_dstate = AX_DSTATE_OPEN;
417 TAILQ_INIT(&(axs->axs_contexts))do { (&(axs->axs_contexts))->tqh_first = ((void *)0
); (&(axs->axs_contexts))->tqh_last = &(&(axs
->axs_contexts))->tqh_first; } while (0)
;
418 TAILQ_INSERT_HEAD(&(ax->ax_sessions), axs, axs_ax_sessions)do { if (((axs)->axs_ax_sessions.tqe_next = (&(ax->
ax_sessions))->tqh_first) != ((void *)0)) (&(ax->ax_sessions
))->tqh_first->axs_ax_sessions.tqe_prev = &(axs)->
axs_ax_sessions.tqe_next; else (&(ax->ax_sessions))->
tqh_last = &(axs)->axs_ax_sessions.tqe_next; (&(ax
->ax_sessions))->tqh_first = (axs); (axs)->axs_ax_sessions
.tqe_prev = &(&(ax->ax_sessions))->tqh_first; }
while (0)
;
419
420 if (ax->ax_cstate == AX_CSTATE_OPEN)
421 (void) agentx_session_start(axs);
422
423 return axs;
424}
425
426static int
427agentx_session_retry(struct agentx_session *axs)
428{
429 struct agentx_context *axc;
430
431#ifdef AX_DEBUG
432 if (axs->axs_cstate != AX_CSTATE_OPEN)
433 agentx_log_axs_fatalx(axs, "%s: unexpected retry", __func__);
434#endif
435
436 TAILQ_FOREACH(axc, &(axs->axs_contexts), axc_axs_contexts)for((axc) = ((&(axs->axs_contexts))->tqh_first); (axc
) != ((void *)0); (axc) = ((axc)->axc_axs_contexts.tqe_next
))
{
437 if (axc->axc_cstate == AX_CSTATE_OPEN) {
438 if (agentx_context_retry(axc) == -1)
439 return -1;
440 } else if (axc->axc_cstate == AX_CSTATE_CLOSE)
441 agentx_context_start(axc);
442 }
443 return 0;
444}
445
446static int
447agentx_session_start(struct agentx_session *axs)
448{
449 struct agentx *ax = axs->axs_ax;
450 uint32_t packetid;
451
452#ifdef AX_DEBUG
453 if (ax->ax_cstate != AX_CSTATE_OPEN ||
454 axs->axs_cstate != AX_CSTATE_CLOSE ||
455 axs->axs_dstate != AX_DSTATE_OPEN)
456 agentx_log_ax_fatalx(ax, "%s: unexpected session open",
457 __func__);
458#endif
459 packetid = ax_open(ax->ax_ax, axs->axs_timeout, &(axs->axs_oid),
460 &(axs->axs_descr));
461 if (packetid == 0) {
462 agentx_log_ax_warn(ax, "couldn't generate %s",
463 ax_pdutype2string(AX_PDU_TYPE_OPEN));
464 agentx_reset(ax);
465 return -1;
466 }
467 axs->axs_packetid = packetid;
468 agentx_log_ax_info(ax, "opening session");
469 axs->axs_cstate = AX_CSTATE_WAITOPEN;
470 return agentx_request(ax, packetid, agentx_session_finalize, axs);
471}
472
473static int
474agentx_session_finalize(struct ax_pdu *pdu, void *cookie)
475{
476 struct agentx_session *axs = cookie;
477 struct agentx *ax = axs->axs_ax;
478 struct agentx_context *axc;
479
480#ifdef AX_DEBUG
481 if (axs->axs_cstate != AX_CSTATE_WAITOPEN)
482 agentx_log_ax_fatalx(ax, "%s: not expecting new session",
483 __func__);
484#endif
485
486 if (pdu->ap_payload.ap_response.ap_error != AX_PDU_ERROR_NOERROR) {
487 agentx_log_ax_warnx(ax, "failed to open session: %s",
488 ax_error2string(pdu->ap_payload.ap_response.ap_error));
489 axs->axs_cstate = AX_CSTATE_CLOSE;
490 return -1;
491 }
492
493 axs->axs_id = pdu->ap_header.aph_sessionid;
494 axs->axs_cstate = AX_CSTATE_OPEN;
495
496 if (axs->axs_dstate == AX_DSTATE_CLOSE) {
497 agentx_session_close(axs, AX_CLOSE_SHUTDOWN);
498 return 0;
499 }
500
501 agentx_log_axs_info(axs, "open");
502
503 TAILQ_FOREACH(axc, &(axs->axs_contexts), axc_axs_contexts)for((axc) = ((&(axs->axs_contexts))->tqh_first); (axc
) != ((void *)0); (axc) = ((axc)->axc_axs_contexts.tqe_next
))
504 agentx_context_start(axc);
505 return 0;
506}
507
508static int
509agentx_session_close(struct agentx_session *axs,
510 enum ax_close_reason reason)
511{
512 struct agentx *ax = axs->axs_ax;
513 uint32_t packetid;
514
515#ifdef AX_DEBUG
516 if (axs->axs_cstate != AX_CSTATE_OPEN)
517 agentx_log_ax_fatalx(ax, "%s: unexpected session close",
518 __func__);
519#endif
520 if ((packetid = ax_close(ax->ax_ax, axs->axs_id, reason)) == 0) {
521 agentx_log_axs_warn(axs, "couldn't generate %s",
522 ax_pdutype2string(AX_PDU_TYPE_CLOSE));
523 agentx_reset(ax);
524 return -1;
525 }
526
527 agentx_log_axs_info(axs, "closing session: %s",
528 ax_closereason2string(reason));
529
530 axs->axs_cstate = AX_CSTATE_WAITCLOSE;
531 return agentx_request(ax, packetid, agentx_session_close_finalize,
532 axs);
533}
534
535static int
536agentx_session_close_finalize(struct ax_pdu *pdu, void *cookie)
537{
538 struct agentx_session *axs = cookie;
539 struct agentx *ax = axs->axs_ax;
540 struct agentx_context *axc, *taxc;
541 int axfree = ax->ax_free;
542
543#ifdef AX_DEBUG
544 if (axs->axs_cstate != AX_CSTATE_WAITCLOSE)
545 agentx_log_axs_fatalx(axs, "%s: not expecting session close",
546 __func__);
547#endif
548
549 if (pdu->ap_payload.ap_response.ap_error != AX_PDU_ERROR_NOERROR) {
550 agentx_log_axs_warnx(axs, "failed to close session: %s",
551 ax_error2string(pdu->ap_payload.ap_response.ap_error));
552 agentx_reset(ax);
553 return -1;
554 }
555
556 axs->axs_cstate = AX_CSTATE_CLOSE;
557 ax->ax_free = 1;
558
559 agentx_log_axs_info(axs, "closed");
560
561 TAILQ_FOREACH_SAFE(axc, &(axs->axs_contexts), axc_axs_contexts, taxc)for ((axc) = ((&(axs->axs_contexts))->tqh_first); (
axc) != ((void *)0) && ((taxc) = ((axc)->axc_axs_contexts
.tqe_next), 1); (axc) = (taxc))
562 agentx_context_reset(axc);
563
564 if (ax->ax_cstate == AX_CSTATE_OPEN &&
565 axs->axs_dstate == AX_DSTATE_OPEN)
566 agentx_session_start(axs);
567 if (!axfree)
568 agentx_free_finalize(ax);
569
570 return 0;
571}
572
573void
574agentx_session_free(struct agentx_session *axs)
575{
576 struct agentx_context *axc, *taxc;
577 struct agentx *ax;
578 int axfree;
579
580 if (axs == NULL((void *)0))
581 return;
582
583 ax = axs->axs_ax;
584 axfree = ax->ax_free;
585 ax->ax_free = 1;
586
587 if (axs->axs_dstate == AX_DSTATE_CLOSE)
588 agentx_log_axs_fatalx(axs, "%s: double free", __func__);
589
590 axs->axs_dstate = AX_DSTATE_CLOSE;
591
592 if (axs->axs_cstate == AX_CSTATE_OPEN)
593 (void) agentx_session_close(axs, AX_CLOSE_SHUTDOWN);
594
595 TAILQ_FOREACH_SAFE(axc, &(axs->axs_contexts), axc_axs_contexts, taxc)for ((axc) = ((&(axs->axs_contexts))->tqh_first); (
axc) != ((void *)0) && ((taxc) = ((axc)->axc_axs_contexts
.tqe_next), 1); (axc) = (taxc))
{
596 if (axc->axc_dstate != AX_DSTATE_CLOSE)
597 agentx_context_free(axc);
598 }
599
600 if (!axfree)
601 agentx_free_finalize(ax);
602}
603
604static void
605agentx_session_free_finalize(struct agentx_session *axs)
606{
607 struct agentx *ax = axs->axs_ax;
608 struct agentx_context *axc, *taxc;
609
610 TAILQ_FOREACH_SAFE(axc, &(axs->axs_contexts), axc_axs_contexts, taxc)for ((axc) = ((&(axs->axs_contexts))->tqh_first); (
axc) != ((void *)0) && ((taxc) = ((axc)->axc_axs_contexts
.tqe_next), 1); (axc) = (taxc))
611 agentx_context_free_finalize(axc);
612
613 if (!TAILQ_EMPTY(&(axs->axs_contexts))(((&(axs->axs_contexts))->tqh_first) == ((void *)0)
)
||
614 axs->axs_cstate != AX_CSTATE_CLOSE ||
615 axs->axs_dstate != AX_DSTATE_CLOSE)
616 return;
617
618 TAILQ_REMOVE(&(ax->ax_sessions), axs, axs_ax_sessions)do { if (((axs)->axs_ax_sessions.tqe_next) != ((void *)0))
(axs)->axs_ax_sessions.tqe_next->axs_ax_sessions.tqe_prev
= (axs)->axs_ax_sessions.tqe_prev; else (&(ax->ax_sessions
))->tqh_last = (axs)->axs_ax_sessions.tqe_prev; *(axs)->
axs_ax_sessions.tqe_prev = (axs)->axs_ax_sessions.tqe_next
; ; ; } while (0)
;
619 free(axs->axs_descr.aos_string);
620 free(axs);
621}
622
623static void
624agentx_session_reset(struct agentx_session *axs)
625{
626 struct agentx_context *axc, *taxc;
627 struct agentx *ax = axs->axs_ax;
628 int axfree = ax->ax_free;
629
630 ax->ax_free = 1;
631
632 axs->axs_cstate = AX_CSTATE_CLOSE;
633
634 TAILQ_FOREACH_SAFE(axc, &(axs->axs_contexts), axc_axs_contexts, taxc)for ((axc) = ((&(axs->axs_contexts))->tqh_first); (
axc) != ((void *)0) && ((taxc) = ((axc)->axc_axs_contexts
.tqe_next), 1); (axc) = (taxc))
635 agentx_context_reset(axc);
636
637 if (!axfree)
638 agentx_free_finalize(ax);
639}
640
641struct agentx_context *
642agentx_context(struct agentx_session *axs, const char *name)
643{
644 struct agentx_context *axc;
645
646 if (axs->axs_dstate == AX_DSTATE_CLOSE)
647 agentx_log_axs_fatalx(axs, "%s: use after free", __func__);
648
649 if ((axc = calloc(1, sizeof(*axc))) == NULL((void *)0))
650 return NULL((void *)0);
651
652 axc->axc_axs = axs;
653 axc->axc_name_default = (name == NULL((void *)0));
654 if (name != NULL((void *)0)) {
655 axc->axc_name.aos_string = (unsigned char *)strdup(name);
656 if (axc->axc_name.aos_string == NULL((void *)0)) {
657 free(axc);
658 return NULL((void *)0);
659 }
660 axc->axc_name.aos_slen = strlen(name);
661 }
662 axc->axc_cstate = axs->axs_cstate == AX_CSTATE_OPEN ?
663 AX_CSTATE_OPEN : AX_CSTATE_CLOSE;
664 axc->axc_dstate = AX_DSTATE_OPEN;
665 TAILQ_INIT(&(axc->axc_agentcaps))do { (&(axc->axc_agentcaps))->tqh_first = ((void *)
0); (&(axc->axc_agentcaps))->tqh_last = &(&
(axc->axc_agentcaps))->tqh_first; } while (0)
;
666 TAILQ_INIT(&(axc->axc_regions))do { (&(axc->axc_regions))->tqh_first = ((void *)0)
; (&(axc->axc_regions))->tqh_last = &(&(axc
->axc_regions))->tqh_first; } while (0)
;
667
668 TAILQ_INSERT_HEAD(&(axs->axs_contexts), axc, axc_axs_contexts)do { if (((axc)->axc_axs_contexts.tqe_next = (&(axs->
axs_contexts))->tqh_first) != ((void *)0)) (&(axs->
axs_contexts))->tqh_first->axc_axs_contexts.tqe_prev = &
(axc)->axc_axs_contexts.tqe_next; else (&(axs->axs_contexts
))->tqh_last = &(axc)->axc_axs_contexts.tqe_next; (
&(axs->axs_contexts))->tqh_first = (axc); (axc)->
axc_axs_contexts.tqe_prev = &(&(axs->axs_contexts)
)->tqh_first; } while (0)
;
669
670 return axc;
671}
672
673static int
674agentx_context_retry(struct agentx_context *axc)
675{
676 struct agentx_agentcaps *axa;
677 struct agentx_region *axr;
678
679#ifdef AX_DEBUG
680 if (axc->axc_cstate != AX_CSTATE_OPEN)
681 agentx_log_axc_fatalx(axc, "%s: unexpected retry", __func__);
682#endif
683
684 TAILQ_FOREACH(axa, &(axc->axc_agentcaps), axa_axc_agentcaps)for((axa) = ((&(axc->axc_agentcaps))->tqh_first); (
axa) != ((void *)0); (axa) = ((axa)->axa_axc_agentcaps.tqe_next
))
{
685 if (axa->axa_cstate == AX_CSTATE_CLOSE) {
686 if (agentx_agentcaps_start(axa) == -1)
687 return -1;
688 }
689 }
690 TAILQ_FOREACH(axr, &(axc->axc_regions), axr_axc_regions)for((axr) = ((&(axc->axc_regions))->tqh_first); (axr
) != ((void *)0); (axr) = ((axr)->axr_axc_regions.tqe_next
))
{
691 if (axr->axr_cstate == AX_CSTATE_OPEN) {
692 if (agentx_region_retry(axr) == -1)
693 return -1;
694 } else if (axr->axr_cstate == AX_CSTATE_CLOSE) {
695 if (agentx_region_start(axr) == -1)
696 return -1;
697 }
698 }
699 return 0;
700}
701
702
703static void
704agentx_context_start(struct agentx_context *axc)
705{
706 struct agentx_agentcaps *axa;
707 struct agentx_region *axr;
708
709#ifdef AX_DEBUG
710 if (axc->axc_cstate != AX_CSTATE_CLOSE)
711 agentx_log_axc_fatalx(axc, "%s: unexpected context start",
712 __func__);
713#endif
714 axc->axc_cstate = AX_CSTATE_OPEN;
715
716 TAILQ_FOREACH(axa, &(axc->axc_agentcaps), axa_axc_agentcaps)for((axa) = ((&(axc->axc_agentcaps))->tqh_first); (
axa) != ((void *)0); (axa) = ((axa)->axa_axc_agentcaps.tqe_next
))
{
717 if (agentx_agentcaps_start(axa) == -1)
718 return;
719 }
720 TAILQ_FOREACH(axr, &(axc->axc_regions), axr_axc_regions)for((axr) = ((&(axc->axc_regions))->tqh_first); (axr
) != ((void *)0); (axr) = ((axr)->axr_axc_regions.tqe_next
))
{
721 if (agentx_region_start(axr) == -1)
722 return;
723 }
724}
725
726uint32_t
727agentx_context_uptime(struct agentx_context *axc)
728{
729 struct timespec cur, res;
730
731 if (axc->axc_sysuptimespec.tv_sec == 0 &&
732 axc->axc_sysuptimespec.tv_nsec == 0)
733 return 0;
734
735 (void) clock_gettime(CLOCK_MONOTONIC3, &cur);
736
737 timespecsub(&cur, &(axc->axc_sysuptimespec), &res)do { (&res)->tv_sec = (&cur)->tv_sec - (&(axc
->axc_sysuptimespec))->tv_sec; (&res)->tv_nsec =
(&cur)->tv_nsec - (&(axc->axc_sysuptimespec))->
tv_nsec; if ((&res)->tv_nsec < 0) { (&res)->
tv_sec--; (&res)->tv_nsec += 1000000000L; } } while (0
)
;
738
739 return axc->axc_sysuptime +
740 (uint32_t) ((res.tv_sec * 100) + (res.tv_nsec / 10000000));
741}
742
743struct agentx_object *
744agentx_context_object_find(struct agentx_context *axc,
745 const uint32_t oid[], size_t oidlen, int active, int instance)
746{
747 struct agentx_object *axo, axo_search;
748 const char *errstr;
749
750 if (agentx_oidfill(&(axo_search.axo_oid), oid, oidlen, &errstr) == -1) {
751 if (oidlen > AGENTX_OID_MIN_LEN2) {
752#ifdef AX_DEBUG
753 agentx_log_axc_fatalx(axc, "%s: %s", __func__, errstr);
754#else
755 agentx_log_axc_warnx(axc, "%s: %s", __func__, errstr);
756 return NULL((void *)0);
757 }
758#endif
759 if (oidlen == 1)
760 axo_search.axo_oid.aoi_id[0] = oid[0];
761 axo_search.axo_oid.aoi_idlen = oidlen;
762 }
763
764 axo = RB_FIND(axc_objects, &(axc->axc_objects), &axo_search)axc_objects_RB_FIND(&(axc->axc_objects), &axo_search
)
;
765 while (axo == NULL((void *)0) && !instance && axo_search.axo_oid.aoi_idlen > 0) {
766 axo = RB_FIND(axc_objects, &(axc->axc_objects), &axo_search)axc_objects_RB_FIND(&(axc->axc_objects), &axo_search
)
;
767 axo_search.axo_oid.aoi_idlen--;
768 }
769 if (active && axo != NULL((void *)0) && axo->axo_cstate != AX_CSTATE_OPEN)
770 return NULL((void *)0);
771 return axo;
772}
773
774struct agentx_object *
775agentx_context_object_nfind(struct agentx_context *axc,
776 const uint32_t oid[], size_t oidlen, int active, int inclusive)
777{
778 struct agentx_object *axo, axo_search;
779 const char *errstr;
780
781 if (agentx_oidfill(&(axo_search.axo_oid), oid, oidlen, &errstr) == -1) {
782 if (oidlen > AGENTX_OID_MIN_LEN2) {
783#ifdef AX_DEBUG
784 agentx_log_axc_fatalx(axc, "%s: %s", __func__, errstr);
785#else
786 agentx_log_axc_warnx(axc, "%s: %s", __func__, errstr);
787 return NULL((void *)0);
788#endif
789 }
790 if (oidlen == 1)
791 axo_search.axo_oid.aoi_id[0] = oid[0];
792 axo_search.axo_oid.aoi_idlen = oidlen;
793 }
794
795 axo = RB_NFIND(axc_objects, &(axc->axc_objects), &axo_search)axc_objects_RB_NFIND(&(axc->axc_objects), &axo_search
)
;
796 if (!inclusive && axo != NULL((void *)0) &&
797 ax_oid_cmp(&(axo->axo_oid), &(axo_search.axo_oid)) <= 0) {
798 axo = RB_NEXT(axc_objects, &(axc->axc_objects), axo)axc_objects_RB_NEXT(axo);
799 }
800
801 while (active && axo != NULL((void *)0) && axo->axo_cstate != AX_CSTATE_OPEN)
802 axo = RB_NEXT(axc_objects, &(axc->axc_objects), axo)axc_objects_RB_NEXT(axo);
803 return axo;
804}
805
806void
807agentx_context_free(struct agentx_context *axc)
808{
809 struct agentx_agentcaps *axa, *taxa;
810 struct agentx_region *axr, *taxr;
811
812 if (axc == NULL((void *)0))
813 return;
814
815#ifdef AX_DEBUG
816 if (axc->axc_dstate == AX_DSTATE_CLOSE)
817 agentx_log_axc_fatalx(axc, "%s: double free", __func__);
818#endif
819 axc->axc_dstate = AX_DSTATE_CLOSE;
820
821 TAILQ_FOREACH_SAFE(axa, &(axc->axc_agentcaps), axa_axc_agentcaps,for ((axa) = ((&(axc->axc_agentcaps))->tqh_first); (
axa) != ((void *)0) && ((taxa) = ((axa)->axa_axc_agentcaps
.tqe_next), 1); (axa) = (taxa))
822 taxa)for ((axa) = ((&(axc->axc_agentcaps))->tqh_first); (
axa) != ((void *)0) && ((taxa) = ((axa)->axa_axc_agentcaps
.tqe_next), 1); (axa) = (taxa))
{
823 if (axa->axa_dstate != AX_DSTATE_CLOSE)
824 agentx_agentcaps_free(axa);
825 }
826 TAILQ_FOREACH_SAFE(axr, &(axc->axc_regions), axr_axc_regions, taxr)for ((axr) = ((&(axc->axc_regions))->tqh_first); (axr
) != ((void *)0) && ((taxr) = ((axr)->axr_axc_regions
.tqe_next), 1); (axr) = (taxr))
{
827 if (axr->axr_dstate != AX_DSTATE_CLOSE)
828 agentx_region_free(axr);
829 }
830}
831
832static void
833agentx_context_free_finalize(struct agentx_context *axc)
834{
835 struct agentx_session *axs = axc->axc_axs;
836 struct agentx_region *axr, *taxr;
837 struct agentx_agentcaps *axa, *taxa;
838
839 TAILQ_FOREACH_SAFE(axa, &(axc->axc_agentcaps), axa_axc_agentcaps, taxa)for ((axa) = ((&(axc->axc_agentcaps))->tqh_first); (
axa) != ((void *)0) && ((taxa) = ((axa)->axa_axc_agentcaps
.tqe_next), 1); (axa) = (taxa))
840 agentx_agentcaps_free_finalize(axa);
841 TAILQ_FOREACH_SAFE(axr, &(axc->axc_regions), axr_axc_regions, taxr)for ((axr) = ((&(axc->axc_regions))->tqh_first); (axr
) != ((void *)0) && ((taxr) = ((axr)->axr_axc_regions
.tqe_next), 1); (axr) = (taxr))
842 agentx_region_free_finalize(axr);
843
844 if (!TAILQ_EMPTY(&(axc->axc_regions))(((&(axc->axc_regions))->tqh_first) == ((void *)0)) ||
845 !TAILQ_EMPTY(&(axc->axc_agentcaps))(((&(axc->axc_agentcaps))->tqh_first) == ((void *)0
))
||
846 axc->axc_cstate != AX_CSTATE_CLOSE ||
847 axc->axc_dstate != AX_DSTATE_CLOSE)
848 return;
849
850 TAILQ_REMOVE(&(axs->axs_contexts), axc, axc_axs_contexts)do { if (((axc)->axc_axs_contexts.tqe_next) != ((void *)0)
) (axc)->axc_axs_contexts.tqe_next->axc_axs_contexts.tqe_prev
= (axc)->axc_axs_contexts.tqe_prev; else (&(axs->axs_contexts
))->tqh_last = (axc)->axc_axs_contexts.tqe_prev; *(axc)
->axc_axs_contexts.tqe_prev = (axc)->axc_axs_contexts.tqe_next
; ; ; } while (0)
;
851 free(axc->axc_name.aos_string);
852 free(axc);
853}
854
855static void
856agentx_context_reset(struct agentx_context *axc)
857{
858 struct agentx_agentcaps *axa, *taxa;
859 struct agentx_region *axr, *taxr;
860 struct agentx *ax = axc->axc_axs->axs_ax;
861 int axfree = ax->ax_free;
862
863 ax->ax_free = 1;
864
865 axc->axc_cstate = AX_CSTATE_CLOSE;
866 axc->axc_sysuptimespec.tv_sec = 0;
867 axc->axc_sysuptimespec.tv_nsec = 0;
868
869 TAILQ_FOREACH_SAFE(axa, &(axc->axc_agentcaps), axa_axc_agentcaps, taxa)for ((axa) = ((&(axc->axc_agentcaps))->tqh_first); (
axa) != ((void *)0) && ((taxa) = ((axa)->axa_axc_agentcaps
.tqe_next), 1); (axa) = (taxa))
870 agentx_agentcaps_reset(axa);
871 TAILQ_FOREACH_SAFE(axr, &(axc->axc_regions), axr_axc_regions, taxr)for ((axr) = ((&(axc->axc_regions))->tqh_first); (axr
) != ((void *)0) && ((taxr) = ((axr)->axr_axc_regions
.tqe_next), 1); (axr) = (taxr))
872 agentx_region_reset(axr);
873
874 if (!axfree)
875 agentx_free_finalize(ax);
876}
877
878struct agentx_agentcaps *
879agentx_agentcaps(struct agentx_context *axc, uint32_t oid[],
880 size_t oidlen, const char *descr)
881{
882 struct agentx_agentcaps *axa;
883 const char *errstr;
884
885 if (axc->axc_dstate == AX_DSTATE_CLOSE)
886 agentx_log_axc_fatalx(axc, "%s: use after free", __func__);
887
888 if ((axa = calloc(1, sizeof(*axa))) == NULL((void *)0))
889 return NULL((void *)0);
890
891 axa->axa_axc = axc;
892 if (agentx_oidfill(&(axa->axa_oid), oid, oidlen, &errstr) == -1) {
893#ifdef AX_DEBUG
894 agentx_log_axc_fatalx(axc, "%s: %s", __func__, errstr);
895#else
896 agentx_log_axc_warnx(axc, "%s: %s", __func__, errstr);
897 return NULL((void *)0);
898#endif
899 }
900 axa->axa_descr.aos_string = (unsigned char *)strdup(descr);
901 if (axa->axa_descr.aos_string == NULL((void *)0)) {
902 free(axa);
903 return NULL((void *)0);
904 }
905 axa->axa_descr.aos_slen = strlen(descr);
906 axa->axa_cstate = AX_CSTATE_CLOSE;
907 axa->axa_dstate = AX_DSTATE_OPEN;
908
909 TAILQ_INSERT_TAIL(&(axc->axc_agentcaps), axa, axa_axc_agentcaps)do { (axa)->axa_axc_agentcaps.tqe_next = ((void *)0); (axa
)->axa_axc_agentcaps.tqe_prev = (&(axc->axc_agentcaps
))->tqh_last; *(&(axc->axc_agentcaps))->tqh_last
= (axa); (&(axc->axc_agentcaps))->tqh_last = &
(axa)->axa_axc_agentcaps.tqe_next; } while (0)
;
910
911 if (axc->axc_cstate == AX_CSTATE_OPEN)
912 agentx_agentcaps_start(axa);
913
914 return axa;
915}
916
917static int
918agentx_agentcaps_start(struct agentx_agentcaps *axa)
919{
920 struct agentx_context *axc = axa->axa_axc;
921 struct agentx_session *axs = axc->axc_axs;
922 struct agentx *ax = axs->axs_ax;
923 uint32_t packetid;
924
925#ifdef AX_DEBUG
926 if (axc->axc_cstate != AX_CSTATE_OPEN ||
927 axa->axa_cstate != AX_CSTATE_CLOSE ||
928 axa->axa_dstate != AX_DSTATE_OPEN)
929 agentx_log_axc_fatalx(axc,
930 "%s: unexpected region registration", __func__);
931#endif
932
933 packetid = ax_addagentcaps(ax->ax_ax, axs->axs_id,
934 AGENTX_CONTEXT_CTX(axc)(axc->axc_name_default ? ((void *)0) : &(axc->axc_name
))
, &(axa->axa_oid), &(axa->axa_descr));
935 if (packetid == 0) {
936 agentx_log_axc_warn(axc, "couldn't generate %s",
937 ax_pdutype2string(AX_PDU_TYPE_ADDAGENTCAPS));
938 agentx_reset(ax);
939 return -1;
940 }
941 agentx_log_axc_info(axc, "agentcaps %s: opening",
942 ax_oid2string(&(axa->axa_oid)));
943 axa->axa_cstate = AX_CSTATE_WAITOPEN;
944 return agentx_request(ax, packetid, agentx_agentcaps_finalize,
945 axa);
946}
947
948static int
949agentx_agentcaps_finalize(struct ax_pdu *pdu, void *cookie)
950{
951 struct agentx_agentcaps *axa = cookie;
952 struct agentx_context *axc = axa->axa_axc;
953
954#ifdef AX_DEBUG
955 if (axa->axa_cstate != AX_CSTATE_WAITOPEN)
956 agentx_log_axc_fatalx(axc,
957 "%s: not expecting agentcaps open", __func__);
958#endif
959
960 if (pdu->ap_payload.ap_response.ap_error != AX_PDU_ERROR_NOERROR) {
961 /* Agentcaps failing is nothing too serious */
962 agentx_log_axc_warn(axc, "agentcaps %s: %s",
963 ax_oid2string(&(axa->axa_oid)),
964 ax_error2string(pdu->ap_payload.ap_response.ap_error));
965 axa->axa_cstate = AX_CSTATE_CLOSE;
966 return 0;
967 }
968
969 axa->axa_cstate = AX_CSTATE_OPEN;
970
971 agentx_log_axc_info(axc, "agentcaps %s: open",
972 ax_oid2string(&(axa->axa_oid)));
973
974 if (axa->axa_dstate == AX_DSTATE_CLOSE)
975 agentx_agentcaps_close(axa);
976
977 return 0;
978}
979
980static int
981agentx_agentcaps_close(struct agentx_agentcaps *axa)
982{
983 struct agentx_context *axc = axa->axa_axc;
984 struct agentx_session *axs = axc->axc_axs;
985 struct agentx *ax = axs->axs_ax;
986 uint32_t packetid;
987
988#ifdef AX_DEBUG
989 if (axa->axa_cstate != AX_CSTATE_OPEN)
990 agentx_log_axc_fatalx(axc, "%s: unexpected agentcaps close",
991 __func__);
992#endif
993
994 axa->axa_cstate = AX_CSTATE_WAITCLOSE;
995 if (axs->axs_cstate == AX_CSTATE_WAITCLOSE)
996 return 0;
997
998 packetid = ax_removeagentcaps(ax->ax_ax, axs->axs_id,
999 AGENTX_CONTEXT_CTX(axc)(axc->axc_name_default ? ((void *)0) : &(axc->axc_name
))
, &(axa->axa_oid));
1000 if (packetid == 0) {
1001 agentx_log_axc_warn(axc, "couldn't generate %s",
1002 ax_pdutype2string(AX_PDU_TYPE_REMOVEAGENTCAPS));
1003 agentx_reset(ax);
1004 return -1;
1005 }
1006 agentx_log_axc_info(axc, "agentcaps %s: closing",
1007 ax_oid2string(&(axa->axa_oid)));
1008 return agentx_request(ax, packetid,
1009 agentx_agentcaps_close_finalize, axa);
1010}
1011
1012static int
1013agentx_agentcaps_close_finalize(struct ax_pdu *pdu, void *cookie)
1014{
1015 struct agentx_agentcaps *axa = cookie;
1016 struct agentx_context *axc = axa->axa_axc;
1017 struct agentx_session *axs = axc->axc_axs;
1018 struct agentx *ax = axs->axs_ax;
1019 int axfree = ax->ax_free;
1020
1021#ifdef AX_DEBUG
1022 if (axa->axa_cstate != AX_CSTATE_WAITCLOSE)
1023 agentx_log_axc_fatalx(axc, "%s: unexpected agentcaps close",
1024 __func__);
1025#endif
1026
1027 if (pdu->ap_payload.ap_response.ap_error != AX_PDU_ERROR_NOERROR) {
1028 agentx_log_axc_warnx(axc, "agentcaps %s: %s",
1029 ax_oid2string(&(axa->axa_oid)),
1030 ax_error2string(pdu->ap_payload.ap_response.ap_error));
1031 agentx_reset(ax);
1032 return -1;
1033 }
1034
1035 axa->axa_cstate = AX_CSTATE_CLOSE;
1036 ax->ax_free = 1;
1037
1038 agentx_log_axc_info(axc, "agentcaps %s: closed",
1039 ax_oid2string(&(axa->axa_oid)));
1040
1041 if (axc->axc_cstate == AX_CSTATE_OPEN &&
1042 axa->axa_dstate == AX_DSTATE_OPEN)
1043 agentx_agentcaps_start(axa);
1044
1045 if (!axfree)
1046 agentx_free_finalize(ax);
1047 return 0;
1048}
1049
1050void
1051agentx_agentcaps_free(struct agentx_agentcaps *axa)
1052{
1053 struct agentx *ax = axa->axa_axc->axc_axs->axs_ax;
1054 int axfree;
1055
1056 if (axa == NULL((void *)0))
1057 return;
1058
1059 axfree = ax->ax_free;
1060 ax->ax_free = 1;
1061
1062 if (axa->axa_dstate == AX_DSTATE_CLOSE)
1063 agentx_log_axc_fatalx(axa->axa_axc, "%s: double free",
1064 __func__);
1065
1066 axa->axa_dstate = AX_DSTATE_CLOSE;
1067
1068 if (axa->axa_cstate == AX_CSTATE_OPEN)
1069 agentx_agentcaps_close(axa);
1070
1071 if (!axfree)
1072 agentx_free_finalize(ax);
1073}
1074
1075static void
1076agentx_agentcaps_free_finalize(struct agentx_agentcaps *axa)
1077{
1078 struct agentx_context *axc = axa->axa_axc;
1079
1080 if (axa->axa_dstate != AX_DSTATE_CLOSE ||
1081 axa->axa_cstate != AX_CSTATE_CLOSE)
1082 return;
1083
1084 TAILQ_REMOVE(&(axc->axc_agentcaps), axa, axa_axc_agentcaps)do { if (((axa)->axa_axc_agentcaps.tqe_next) != ((void *)0
)) (axa)->axa_axc_agentcaps.tqe_next->axa_axc_agentcaps
.tqe_prev = (axa)->axa_axc_agentcaps.tqe_prev; else (&
(axc->axc_agentcaps))->tqh_last = (axa)->axa_axc_agentcaps
.tqe_prev; *(axa)->axa_axc_agentcaps.tqe_prev = (axa)->
axa_axc_agentcaps.tqe_next; ; ; } while (0)
;
1085 free(axa->axa_descr.aos_string);
1086 free(axa);
1087}
1088
1089static void
1090agentx_agentcaps_reset(struct agentx_agentcaps *axa)
1091{
1092 struct agentx *ax = axa->axa_axc->axc_axs->axs_ax;
1093
1094 axa->axa_cstate = AX_CSTATE_CLOSE;
1095
1096 if (!ax->ax_free)
1097 agentx_free_finalize(ax);
1098}
1099
1100struct agentx_region *
1101agentx_region(struct agentx_context *axc, uint32_t oid[],
1102 size_t oidlen, uint8_t timeout)
1103{
1104 struct agentx_region *axr;
1105 struct ax_oid tmpoid;
1106 const char *errstr;
1107
1108 if (axc->axc_dstate == AX_DSTATE_CLOSE)
1109 agentx_log_axc_fatalx(axc, "%s: use after free", __func__);
1110
1111 if (agentx_oidfill(&tmpoid, oid, oidlen, &errstr) == -1) {
1112#ifdef AX_DEBUG
1113 agentx_log_axc_fatalx(axc, "%s: %s", __func__, errstr);
1114#else
1115 return NULL((void *)0);
1116#endif
1117
1118 }
1119 TAILQ_FOREACH(axr, &(axc->axc_regions), axr_axc_regions)for((axr) = ((&(axc->axc_regions))->tqh_first); (axr
) != ((void *)0); (axr) = ((axr)->axr_axc_regions.tqe_next
))
{
1120 if (ax_oid_cmp(&(axr->axr_oid), &tmpoid) == 0) {
1121#ifdef AX_DEBUG
1122 agentx_log_axc_fatalx(axc,
1123 "%s: duplicate region registration", __func__);
1124#else
1125 errno(*__errno()) = EINVAL22;
1126 return NULL((void *)0);
1127#endif
1128 }
1129 }
1130
1131 if ((axr = calloc(1, sizeof(*axr))) == NULL((void *)0))
1132 return NULL((void *)0);
1133
1134 axr->axr_axc = axc;
1135 axr->axr_timeout = timeout;
1136 axr->axr_priority = AX_PRIORITY_DEFAULT127;
1137 bcopy(&tmpoid, &(axr->axr_oid), sizeof(axr->axr_oid));
1138 axr->axr_cstate = AX_CSTATE_CLOSE;
1139 axr->axr_dstate = AX_DSTATE_OPEN;
1140 TAILQ_INIT(&(axr->axr_indices))do { (&(axr->axr_indices))->tqh_first = ((void *)0)
; (&(axr->axr_indices))->tqh_last = &(&(axr
->axr_indices))->tqh_first; } while (0)
;
1141 TAILQ_INIT(&(axr->axr_objects))do { (&(axr->axr_objects))->tqh_first = ((void *)0)
; (&(axr->axr_objects))->tqh_last = &(&(axr
->axr_objects))->tqh_first; } while (0)
;
1142
1143 TAILQ_INSERT_HEAD(&(axc->axc_regions), axr, axr_axc_regions)do { if (((axr)->axr_axc_regions.tqe_next = (&(axc->
axc_regions))->tqh_first) != ((void *)0)) (&(axc->axc_regions
))->tqh_first->axr_axc_regions.tqe_prev = &(axr)->
axr_axc_regions.tqe_next; else (&(axc->axc_regions))->
tqh_last = &(axr)->axr_axc_regions.tqe_next; (&(axc
->axc_regions))->tqh_first = (axr); (axr)->axr_axc_regions
.tqe_prev = &(&(axc->axc_regions))->tqh_first; }
while (0)
;
1144
1145 if (axc->axc_cstate == AX_CSTATE_OPEN)
1146 (void) agentx_region_start(axr);
1147
1148 return axr;
1149}
1150
1151static int
1152agentx_region_retry(struct agentx_region *axr)
1153{
1154 struct agentx_index *axi;
1155 struct agentx_object *axo;
1156
1157#ifdef AX_DEBUG
1158 if (axr->axr_cstate != AX_CSTATE_OPEN)
1159 agentx_log_axc_fatalx(axr->axr_axc,
1160 "%s: unexpected retry", __func__);
1161#endif
1162
1163 TAILQ_FOREACH(axi, &(axr->axr_indices), axi_axr_indices)for((axi) = ((&(axr->axr_indices))->tqh_first); (axi
) != ((void *)0); (axi) = ((axi)->axi_axr_indices.tqe_next
))
{
1164 if (axi->axi_cstate == AX_CSTATE_CLOSE) {
1165 if (agentx_index_start(axi) == -1)
1166 return -1;
1167 }
1168 }
1169 TAILQ_FOREACH(axo, &(axr->axr_objects), axo_axr_objects)for((axo) = ((&(axr->axr_objects))->tqh_first); (axo
) != ((void *)0); (axo) = ((axo)->axo_axr_objects.tqe_next
))
{
1170 if (axo->axo_cstate == AX_CSTATE_CLOSE) {
1171 if (agentx_object_start(axo) == -1)
1172 return -1;
1173 }
1174 }
1175 return 0;
1176}
1177
1178static int
1179agentx_region_start(struct agentx_region *axr)
1180{
1181 struct agentx_context *axc = axr->axr_axc;
1182 struct agentx_session *axs = axc->axc_axs;
1183 struct agentx *ax = axs->axs_ax;
1184 uint32_t packetid;
1185
1186#ifdef AX_DEBUG
1187 if (axc->axc_cstate != AX_CSTATE_OPEN ||
1188 axr->axr_cstate != AX_CSTATE_CLOSE ||
1189 axr->axr_dstate != AX_DSTATE_OPEN)
1190 agentx_log_axc_fatalx(axc,
1191 "%s: unexpected region registration", __func__);
1192#endif
1193
1194 packetid = ax_register(ax->ax_ax, 0, axs->axs_id,
1195 AGENTX_CONTEXT_CTX(axc)(axc->axc_name_default ? ((void *)0) : &(axc->axc_name
))
, axr->axr_timeout, axr->axr_priority,
1196 0, &(axr->axr_oid), 0);
1197 if (packetid == 0) {
1198 agentx_log_axc_warn(axc, "couldn't generate %s",
1199 ax_pdutype2string(AX_PDU_TYPE_REGISTER));
1200 agentx_reset(ax);
1201 return -1;
1202 }
1203 agentx_log_axc_info(axc, "region %s: opening",
1204 ax_oid2string(&(axr->axr_oid)));
1205 axr->axr_cstate = AX_CSTATE_WAITOPEN;
1206 return agentx_request(ax, packetid, agentx_region_finalize, axr);
1207}
1208
1209static int
1210agentx_region_finalize(struct ax_pdu *pdu, void *cookie)
1211{
1212 struct agentx_region *axr = cookie;
1213 struct agentx_context *axc = axr->axr_axc;
1214 struct agentx_index *axi;
1215 struct agentx_object *axo;
1216
1217#ifdef AX_DEBUG
1218 if (axr->axr_cstate != AX_CSTATE_WAITOPEN)
1219 agentx_log_axc_fatalx(axc, "%s: not expecting region open",
1220 __func__);
1221#endif
1222
1223 if (pdu->ap_payload.ap_response.ap_error == AX_PDU_ERROR_NOERROR) {
1224 axr->axr_cstate = AX_CSTATE_OPEN;
1225 agentx_log_axc_info(axc, "region %s: open",
1226 ax_oid2string(&(axr->axr_oid)));
1227 } else if (pdu->ap_payload.ap_response.ap_error ==
1228 AX_PDU_ERROR_DUPLICATEREGISTRATION) {
1229 axr->axr_cstate = AX_CSTATE_CLOSE;
1230 /* Try at lower priority: first come first serve */
1231 if ((++axr->axr_priority) != 0) {
1232 agentx_log_axc_warnx(axc, "region %s: duplicate, "
1233 "reducing priority",
1234 ax_oid2string(&(axr->axr_oid)));
1235 return agentx_region_start(axr);
1236 }
1237 agentx_log_axc_info(axc, "region %s: duplicate, can't "
1238 "reduce priority, ignoring",
1239 ax_oid2string(&(axr->axr_oid)));
1240 } else {
1241 axr->axr_cstate = AX_CSTATE_CLOSE;
1242 agentx_log_axc_warnx(axc, "region %s: %s",
1243 ax_oid2string(&(axr->axr_oid)),
1244 ax_error2string(pdu->ap_payload.ap_response.ap_error));
1245 return -1;
1246 }
1247
1248 if (axr->axr_dstate == AX_DSTATE_CLOSE) {
1249 if (agentx_region_close(axr) == -1)
1250 return -1;
1251 } else {
1252 TAILQ_FOREACH(axi, &(axr->axr_indices), axi_axr_indices)for((axi) = ((&(axr->axr_indices))->tqh_first); (axi
) != ((void *)0); (axi) = ((axi)->axi_axr_indices.tqe_next
))
{
1253 if (agentx_index_start(axi) == -1)
1254 return -1;
1255 }
1256 TAILQ_FOREACH(axo, &(axr->axr_objects), axo_axr_objects)for((axo) = ((&(axr->axr_objects))->tqh_first); (axo
) != ((void *)0); (axo) = ((axo)->axo_axr_objects.tqe_next
))
{
1257 if (agentx_object_start(axo) == -1)
1258 return -1;
1259 }
1260 }
1261 return 0;
1262}
1263
1264static int
1265agentx_region_close(struct agentx_region *axr)
1266{
1267 struct agentx_context *axc = axr->axr_axc;
1268 struct agentx_session *axs = axc->axc_axs;
1269 struct agentx *ax = axs->axs_ax;
1270 uint32_t packetid;
1271
1272#ifdef AX_DEBUG
1273 if (axr->axr_cstate != AX_CSTATE_OPEN)
1274 agentx_log_axc_fatalx(axc, "%s: unexpected region close",
1275 __func__);
1276#endif
1277
1278 axr->axr_cstate = AX_CSTATE_WAITCLOSE;
1279 if (axs->axs_cstate == AX_CSTATE_WAITCLOSE)
1280 return 0;
1281
1282 packetid = ax_unregister(ax->ax_ax, axs->axs_id,
1283 AGENTX_CONTEXT_CTX(axc)(axc->axc_name_default ? ((void *)0) : &(axc->axc_name
))
, axr->axr_priority, 0, &(axr->axr_oid),
1284 0);
1285 if (packetid == 0) {
1286 agentx_log_axc_warn(axc, "couldn't generate %s",
1287 ax_pdutype2string(AX_PDU_TYPE_UNREGISTER));
1288 agentx_reset(ax);
1289 return -1;
1290 }
1291 agentx_log_axc_info(axc, "region %s: closing",
1292 ax_oid2string(&(axr->axr_oid)));
1293 return agentx_request(ax, packetid, agentx_region_close_finalize,
1294 axr);
1295}
1296
1297static int
1298agentx_region_close_finalize(struct ax_pdu *pdu, void *cookie)
1299{
1300 struct agentx_region *axr = cookie;
1301 struct agentx_context *axc = axr->axr_axc;
1302 struct agentx_session *axs = axc->axc_axs;
1303 struct agentx *ax = axs->axs_ax;
1304 int axfree = ax->ax_free;
1305
1306#ifdef AX_DEBUG
1307 if (axr->axr_cstate != AX_CSTATE_WAITCLOSE)
1308 agentx_log_axc_fatalx(axc, "%s: unexpected region close",
1309 __func__);
1310#endif
1311
1312 if (pdu->ap_payload.ap_response.ap_error != AX_PDU_ERROR_NOERROR) {
1313 agentx_log_axc_warnx(axc, "closing %s: %s",
1314 ax_oid2string(&(axr->axr_oid)),
1315 ax_error2string(pdu->ap_payload.ap_response.ap_error));
1316 agentx_reset(ax);
1317 return -1;
1318 }
1319
1320 ax->ax_free = 1;
1321 axr->axr_priority = AX_PRIORITY_DEFAULT127;
1322 axr->axr_cstate = AX_CSTATE_CLOSE;
1323
1324 agentx_log_axc_info(axc, "region %s: closed",
1325 ax_oid2string(&(axr->axr_oid)));
1326
1327 if (axc->axc_cstate == AX_CSTATE_OPEN &&
1328 axr->axr_dstate == AX_DSTATE_OPEN)
1329 agentx_region_start(axr);
1330
1331 if (!axfree)
1332 agentx_free_finalize(ax);
1333 return 0;
1334}
1335
1336void
1337agentx_region_free(struct agentx_region *axr)
1338{
1339 struct agentx_index *axi, *taxi;
1340 struct agentx_object *axo, *taxo;
1341 struct agentx *ax;
1342 int axfree;
1343
1344 if (axr == NULL((void *)0))
1345 return;
1346
1347 ax = axr->axr_axc->axc_axs->axs_ax;
1348 axfree = ax->ax_free;
1349 ax->ax_free = 1;
1350
1351 if (axr->axr_dstate == AX_DSTATE_CLOSE)
1352 agentx_log_axc_fatalx(axr->axr_axc, "%s: double free",
1353 __func__);
1354
1355 axr->axr_dstate = AX_DSTATE_CLOSE;
1356
1357 TAILQ_FOREACH_SAFE(axi, &(axr->axr_indices), axi_axr_indices, taxi)for ((axi) = ((&(axr->axr_indices))->tqh_first); (axi
) != ((void *)0) && ((taxi) = ((axi)->axi_axr_indices
.tqe_next), 1); (axi) = (taxi))
{
1358 if (axi->axi_dstate != AX_DSTATE_CLOSE)
1359 agentx_index_free(axi);
1360 }
1361
1362 TAILQ_FOREACH_SAFE(axo, &(axr->axr_objects), axo_axr_objects, taxo)for ((axo) = ((&(axr->axr_objects))->tqh_first); (axo
) != ((void *)0) && ((taxo) = ((axo)->axo_axr_objects
.tqe_next), 1); (axo) = (taxo))
{
1363 if (axo->axo_dstate != AX_DSTATE_CLOSE)
1364 agentx_object_free(axo);
1365 }
1366
1367 if (axr->axr_cstate == AX_CSTATE_OPEN)
1368 agentx_region_close(axr);
1369
1370 if (!axfree)
1371 agentx_free_finalize(ax);
1372}
1373
1374static void
1375agentx_region_free_finalize(struct agentx_region *axr)
1376{
1377 struct agentx_context *axc = axr->axr_axc;
1378 struct agentx_index *axi, *taxi;
1379 struct agentx_object *axo, *taxo;
1380
1381 TAILQ_FOREACH_SAFE(axo, &(axr->axr_objects), axo_axr_objects, taxo)for ((axo) = ((&(axr->axr_objects))->tqh_first); (axo
) != ((void *)0) && ((taxo) = ((axo)->axo_axr_objects
.tqe_next), 1); (axo) = (taxo))
1382 agentx_object_free_finalize(axo);
1383 TAILQ_FOREACH_SAFE(axi, &(axr->axr_indices), axi_axr_indices, taxi)for ((axi) = ((&(axr->axr_indices))->tqh_first); (axi
) != ((void *)0) && ((taxi) = ((axi)->axi_axr_indices
.tqe_next), 1); (axi) = (taxi))
1384 agentx_index_free_finalize(axi);
1385
1386 if (!TAILQ_EMPTY(&(axr->axr_indices))(((&(axr->axr_indices))->tqh_first) == ((void *)0)) ||
1387 !TAILQ_EMPTY(&(axr->axr_objects))(((&(axr->axr_objects))->tqh_first) == ((void *)0)) ||
1388 axr->axr_cstate != AX_CSTATE_CLOSE ||
1389 axr->axr_dstate != AX_DSTATE_CLOSE)
1390 return;
1391
1392 TAILQ_REMOVE(&(axc->axc_regions), axr, axr_axc_regions)do { if (((axr)->axr_axc_regions.tqe_next) != ((void *)0))
(axr)->axr_axc_regions.tqe_next->axr_axc_regions.tqe_prev
= (axr)->axr_axc_regions.tqe_prev; else (&(axc->axc_regions
))->tqh_last = (axr)->axr_axc_regions.tqe_prev; *(axr)->
axr_axc_regions.tqe_prev = (axr)->axr_axc_regions.tqe_next
; ; ; } while (0)
;
1393 free(axr);
1394}
1395
1396static void
1397agentx_region_reset(struct agentx_region *axr)
1398{
1399 struct agentx_index *axi, *taxi;
1400 struct agentx_object *axo, *taxo;
1401 struct agentx *ax = axr->axr_axc->axc_axs->axs_ax;
1402 int axfree = ax->ax_free;
1403
1404 axr->axr_cstate = AX_CSTATE_CLOSE;
1405 axr->axr_priority = AX_PRIORITY_DEFAULT127;
1406 ax->ax_free = 1;
1407
1408 TAILQ_FOREACH_SAFE(axi, &(axr->axr_indices), axi_axr_indices, taxi)for ((axi) = ((&(axr->axr_indices))->tqh_first); (axi
) != ((void *)0) && ((taxi) = ((axi)->axi_axr_indices
.tqe_next), 1); (axi) = (taxi))
1409 agentx_index_reset(axi);
1410 TAILQ_FOREACH_SAFE(axo, &(axr->axr_objects), axo_axr_objects, taxo)for ((axo) = ((&(axr->axr_objects))->tqh_first); (axo
) != ((void *)0) && ((taxo) = ((axo)->axo_axr_objects
.tqe_next), 1); (axo) = (taxo))
1411 agentx_object_reset(axo);
1412
1413 if (!axfree)
1414 agentx_free_finalize(ax);
1415}
1416
1417struct agentx_index *
1418agentx_index_integer_new(struct agentx_region *axr, uint32_t oid[],
1419 size_t oidlen)
1420{
1421 struct ax_varbind vb;
1422 const char *errstr;
1423
1424 vb.avb_type = AX_DATA_TYPE_INTEGER;
1425 if (agentx_oidfill(&(vb.avb_oid), oid, oidlen, &errstr) == -1) {
1426#ifdef AX_DEBUG
1427 agentx_log_axc_fatalx(axr->axr_axc, "%s: %s", __func__, errstr);
1428#else
1429 agentx_log_axc_warnx(axr->axr_axc, "%s: %s", __func__, errstr);
1430 return NULL((void *)0);
1431#endif
1432 }
1433 vb.avb_data.avb_int32 = 0;
1434
1435 return agentx_index(axr, &vb, AXI_TYPE_NEW);
1436}
1437
1438struct agentx_index *
1439agentx_index_integer_any(struct agentx_region *axr, uint32_t oid[],
1440 size_t oidlen)
1441{
1442 struct ax_varbind vb;
1443 const char *errstr;
1444
1445 vb.avb_type = AX_DATA_TYPE_INTEGER;
1446 if (agentx_oidfill(&(vb.avb_oid), oid, oidlen, &errstr) == -1) {
1447#ifdef AX_DEBUG
1448 agentx_log_axc_fatalx(axr->axr_axc, "%s: %s", __func__, errstr);
1449#else
1450 agentx_log_axc_warnx(axr->axr_axc, "%s: %s", __func__, errstr);
1451 return NULL((void *)0);
1452#endif
1453 }
1454 vb.avb_data.avb_int32 = 0;
1455
1456 return agentx_index(axr, &vb, AXI_TYPE_ANY);
1457}
1458
1459struct agentx_index *
1460agentx_index_integer_value(struct agentx_region *axr, uint32_t oid[],
1461 size_t oidlen, int32_t value)
1462{
1463 struct ax_varbind vb;
1464 const char *errstr;
1465
1466 if (value < 0) {
1467#ifdef AX_DEBUG
1468 agentx_log_axc_fatalx(axr->axr_axc, "%s: value < 0", __func__);
1469#else
1470 agentx_log_axc_warnx(axr->axr_axc, "%s: value < 0", __func__);
1471 errno(*__errno()) = EINVAL22;
1472 return NULL((void *)0);
1473#endif
1474 }
1475
1476 vb.avb_type = AX_DATA_TYPE_INTEGER;
1477 if (agentx_oidfill(&(vb.avb_oid), oid, oidlen, &errstr) == -1) {
1478#ifdef AX_DEBUG
1479 agentx_log_axc_fatalx(axr->axr_axc, "%s: %s", __func__, errstr);
1480#else
1481 agentx_log_axc_warnx(axr->axr_axc, "%s: %s", __func__, errstr);
1482 return NULL((void *)0);
1483#endif
1484 }
1485 vb.avb_data.avb_int32 = value;
1486
1487 return agentx_index(axr, &vb, AXI_TYPE_VALUE);
1488}
1489
1490struct agentx_index *
1491agentx_index_integer_dynamic(struct agentx_region *axr, uint32_t oid[],
1492 size_t oidlen)
1493{
1494 struct ax_varbind vb;
1495 const char *errstr;
1496
1497 vb.avb_type = AX_DATA_TYPE_INTEGER;
1498 if (agentx_oidfill(&(vb.avb_oid), oid, oidlen, &errstr) == -1) {
1499#ifdef AX_DEBUG
1500 agentx_log_axc_fatalx(axr->axr_axc, "%s: %s", __func__, errstr);
1501#else
1502 agentx_log_axc_warnx(axr->axr_axc, "%s: %s", __func__, errstr);
1503 return NULL((void *)0);
1504#endif
1505 }
1506
1507 return agentx_index(axr, &vb, AXI_TYPE_DYNAMIC);
1508}
1509
1510struct agentx_index *
1511agentx_index_string_dynamic(struct agentx_region *axr, uint32_t oid[],
1512 size_t oidlen)
1513{
1514 struct ax_varbind vb;
1515 const char *errstr;
1516
1517 vb.avb_type = AX_DATA_TYPE_OCTETSTRING;
1518 if (agentx_oidfill(&(vb.avb_oid), oid, oidlen, &errstr) == -1) {
1519#ifdef AX_DEBUG
1520 agentx_log_axc_fatalx(axr->axr_axc, "%s: %s", __func__, errstr);
1521#else
1522 agentx_log_axc_warnx(axr->axr_axc, "%s: %s", __func__, errstr);
1523 return NULL((void *)0);
1524#endif
1525 }
1526 vb.avb_data.avb_ostring.aos_slen = 0;
1527 vb.avb_data.avb_ostring.aos_string = NULL((void *)0);
1528
1529 return agentx_index(axr, &vb, AXI_TYPE_DYNAMIC);
1530}
1531
1532struct agentx_index *
1533agentx_index_nstring_dynamic(struct agentx_region *axr, uint32_t oid[],
1534 size_t oidlen, size_t vlen)
1535{
1536 struct ax_varbind vb;
1537 const char *errstr;
1538
1539 if (vlen == 0 || vlen > AGENTX_OID_MAX_LEN128) {
1540#ifdef AX_DEBUG
1541 agentx_log_axc_fatalx(axr->axr_axc, "%s: invalid string "
1542 "length: %zu\n", __func__, vlen);
1543#else
1544 agentx_log_axc_warnx(axr->axr_axc, "%s: invalid string "
1545 "length: %zu\n", __func__, vlen);
1546 errno(*__errno()) = EINVAL22;
1547 return NULL((void *)0);
1548#endif
1549 }
1550
1551 vb.avb_type = AX_DATA_TYPE_OCTETSTRING;
1552 if (agentx_oidfill(&(vb.avb_oid), oid, oidlen, &errstr) == -1) {
1553#ifdef AX_DEBUG
1554 agentx_log_axc_fatalx(axr->axr_axc, "%s: %s", __func__, errstr);
1555#else
1556 agentx_log_axc_warnx(axr->axr_axc, "%s: %s", __func__, errstr);
1557 return NULL((void *)0);
1558#endif
1559 }
1560 vb.avb_data.avb_ostring.aos_slen = vlen;
1561 vb.avb_data.avb_ostring.aos_string = NULL((void *)0);
1562
1563 return agentx_index(axr, &vb, AXI_TYPE_DYNAMIC);
1564}
1565
1566struct agentx_index *
1567agentx_index_oid_dynamic(struct agentx_region *axr, uint32_t oid[],
1568 size_t oidlen)
1569{
1570 struct ax_varbind vb;
1571 const char *errstr;
1572
1573 vb.avb_type = AX_DATA_TYPE_OID;
1574 if (agentx_oidfill(&(vb.avb_oid), oid, oidlen, &errstr) == -1) {
1575#ifdef AX_DEBUG
1576 agentx_log_axc_fatalx(axr->axr_axc, "%s: %s", __func__, errstr);
1577#else
1578 agentx_log_axc_warnx(axr->axr_axc, "%s: %s", __func__, errstr);
1579 return NULL((void *)0);
1580#endif
1581 }
1582 vb.avb_data.avb_oid.aoi_idlen = 0;
1583
1584 return agentx_index(axr, &vb, AXI_TYPE_DYNAMIC);
1585}
1586
1587struct agentx_index *
1588agentx_index_noid_dynamic(struct agentx_region *axr, uint32_t oid[],
1589 size_t oidlen, size_t vlen)
1590{
1591 struct ax_varbind vb;
1592 const char *errstr;
1593
1594 if (vlen < AGENTX_OID_MIN_LEN2 || vlen > AGENTX_OID_MAX_LEN128) {
1595#ifdef AX_DEBUG
1596 agentx_log_axc_fatalx(axr->axr_axc, "%s: invalid string "
1597 "length: %zu\n", __func__, vlen);
1598#else
1599 agentx_log_axc_warnx(axr->axr_axc, "%s: invalid string "
1600 "length: %zu\n", __func__, vlen);
1601 errno(*__errno()) = EINVAL22;
1602 return NULL((void *)0);
1603#endif
1604 }
1605
1606 vb.avb_type = AX_DATA_TYPE_OID;
1607 if (agentx_oidfill(&(vb.avb_oid), oid, oidlen, &errstr) == -1) {
1608#ifdef AX_DEBUG
1609 agentx_log_axc_fatalx(axr->axr_axc, "%s: %s", __func__, errstr);
1610#else
1611 agentx_log_axc_warnx(axr->axr_axc, "%s: %s", __func__, errstr);
1612 return NULL((void *)0);
1613#endif
1614 }
1615 vb.avb_data.avb_oid.aoi_idlen = vlen;
1616
1617 return agentx_index(axr, &vb, AXI_TYPE_DYNAMIC);
1618}
1619
1620struct agentx_index *
1621agentx_index_ipaddress_dynamic(struct agentx_region *axr, uint32_t oid[],
1622 size_t oidlen)
1623{
1624 struct ax_varbind vb;
1625 const char *errstr;
1626
1627 vb.avb_type = AX_DATA_TYPE_IPADDRESS;
1628 if (agentx_oidfill(&(vb.avb_oid), oid, oidlen, &errstr) == -1) {
1629#ifdef AX_DEBUG
1630 agentx_log_axc_fatalx(axr->axr_axc, "%s: %s", __func__, errstr);
1631#else
1632 agentx_log_axc_warnx(axr->axr_axc, "%s: %s", __func__, errstr);
1633 return NULL((void *)0);
1634#endif
1635 }
1636 vb.avb_data.avb_ostring.aos_string = NULL((void *)0);
1637
1638 return agentx_index(axr, &vb, AXI_TYPE_DYNAMIC);
1639}
1640
1641static struct agentx_index *
1642agentx_index(struct agentx_region *axr, struct ax_varbind *vb,
1643 enum agentx_index_type type)
1644{
1645 struct agentx_index *axi;
1646
1647 if (axr->axr_dstate == AX_DSTATE_CLOSE)
1648 agentx_log_axc_fatalx(axr->axr_axc, "%s: use after free",
1649 __func__);
1650 if (ax_oid_cmp(&(axr->axr_oid), &(vb->avb_oid)) != -2) {
1651#ifdef AX_DEBUG
1652 agentx_log_axc_fatalx(axr->axr_axc, "%s: oid is not child "
1653 "of region %s", __func__,
1654 ax_oid2string(&(vb->avb_oid)));
1655#else
1656 agentx_log_axc_warnx(axr->axr_axc, "%s: oid is not child of "
1657 "region %s", __func__, ax_oid2string(&(vb->avb_oid)));
1658 errno(*__errno()) = EINVAL22;
1659 return NULL((void *)0);
1660#endif
1661 }
1662
1663 if ((axi = calloc(1, sizeof(*axi))) == NULL((void *)0))
1664 return NULL((void *)0);
1665
1666 axi->axi_axr = axr;
1667 axi->axi_type = type;
1668 bcopy(vb, &(axi->axi_vb), sizeof(*vb));
1669 axi->axi_cstate = AX_CSTATE_CLOSE;
1670 axi->axi_dstate = AX_DSTATE_OPEN;
1671 TAILQ_INSERT_HEAD(&(axr->axr_indices), axi, axi_axr_indices)do { if (((axi)->axi_axr_indices.tqe_next = (&(axr->
axr_indices))->tqh_first) != ((void *)0)) (&(axr->axr_indices
))->tqh_first->axi_axr_indices.tqe_prev = &(axi)->
axi_axr_indices.tqe_next; else (&(axr->axr_indices))->
tqh_last = &(axi)->axi_axr_indices.tqe_next; (&(axr
->axr_indices))->tqh_first = (axi); (axi)->axi_axr_indices
.tqe_prev = &(&(axr->axr_indices))->tqh_first; }
while (0)
;
1672
1673 if (axr->axr_cstate == AX_CSTATE_OPEN)
1674 agentx_index_start(axi);
1675
1676 return axi;
1677}
1678
1679static int
1680agentx_index_start(struct agentx_index *axi)
1681{
1682 struct agentx_region *axr = axi->axi_axr;
1683 struct agentx_context *axc = axr->axr_axc;
1684 struct agentx_session *axs = axc->axc_axs;
1685 struct agentx *ax = axs->axs_ax;
1686 uint32_t packetid;
1687 int flags = 0;
1688
1689#ifdef AX_DEBUG
1690 if (axr->axr_cstate != AX_CSTATE_OPEN ||
1691 axi->axi_cstate != AX_CSTATE_CLOSE ||
1692 axi->axi_dstate != AX_DSTATE_OPEN)
1693 agentx_log_axc_fatalx(axc, "%s: unexpected index allocation",
1694 __func__);
1695#endif
1696
1697 axi->axi_cstate = AX_CSTATE_WAITOPEN;
1698
1699 if (axi->axi_type == AXI_TYPE_NEW)
1700 flags = AX_PDU_FLAG_NEW_INDEX(1 << 1);
1701 else if (axi->axi_type == AXI_TYPE_ANY)
1702 flags = AX_PDU_FLAG_ANY_INDEX(1 << 2);
1703 else if (axi->axi_type == AXI_TYPE_DYNAMIC) {
1704 agentx_index_finalize(NULL((void *)0), axi);
1705 return 0;
1706 }
1707
1708 /* We might be able to bundle, but if we fail we'd have to reorganise */
1709 packetid = ax_indexallocate(ax->ax_ax, flags, axs->axs_id,
1710 AGENTX_CONTEXT_CTX(axc)(axc->axc_name_default ? ((void *)0) : &(axc->axc_name
))
, &(axi->axi_vb), 1);
1711 if (packetid == 0) {
1712 agentx_log_axc_warn(axc, "couldn't generate %s",
1713 ax_pdutype2string(AX_PDU_TYPE_INDEXDEALLOCATE));
1714 agentx_reset(ax);
1715 return -1;
1716 }
1717 if (axi->axi_type == AXI_TYPE_VALUE)
1718 agentx_log_axc_info(axc, "index %s: allocating '%d'",
1719 ax_oid2string(&(axi->axi_vb.avb_oid)),
1720 axi->axi_vb.avb_data.avb_int32);
1721 else if (axi->axi_type == AXI_TYPE_ANY)
1722 agentx_log_axc_info(axc, "index %s: allocating any index",
1723 ax_oid2string(&(axi->axi_vb.avb_oid)));
1724 else if (axi->axi_type == AXI_TYPE_NEW)
1725 agentx_log_axc_info(axc, "index %s: allocating new index",
1726 ax_oid2string(&(axi->axi_vb.avb_oid)));
1727
1728 return agentx_request(ax, packetid, agentx_index_finalize, axi);
1729}
1730
1731static int
1732agentx_index_finalize(struct ax_pdu *pdu, void *cookie)
1733{
1734 struct agentx_index *axi = cookie;
1735 struct agentx_region *axr = axi->axi_axr;
1736 struct agentx_context *axc = axr->axr_axc;
1737 struct ax_pdu_response *resp;
1738 size_t i;
1739
1740#ifdef AX_DEBUG
1741 if (axi->axi_cstate != AX_CSTATE_WAITOPEN)
1742 agentx_log_axc_fatalx(axc,
1743 "%s: not expecting index allocate", __func__);
1744#endif
1745 if (axi->axi_type == AXI_TYPE_DYNAMIC) {
1746 axi->axi_cstate = AX_CSTATE_OPEN;
1747 goto objects_start;
1748 }
1749
1750 resp = &(pdu->ap_payload.ap_response);
1751 if (resp->ap_error != AX_PDU_ERROR_NOERROR) {
1752 axi->axi_cstate = AX_CSTATE_CLOSE;
1753 agentx_log_axc_warnx(axc, "index %s: %s",
1754 ax_oid2string(&(axr->axr_oid)),
1755 ax_error2string(resp->ap_error));
1756 return 0;
1757 }
1758 axi->axi_cstate = AX_CSTATE_OPEN;
1759 if (resp->ap_nvarbind != 1) {
1760 agentx_log_axc_warnx(axc, "index %s: unexpected number of "
1761 "indices", ax_oid2string(&(axr->axr_oid)));
1762 axi->axi_cstate = AX_CSTATE_CLOSE;
1763 return -1;
1764 }
1765 if (resp->ap_varbindlist[0].avb_type != axi->axi_vb.avb_type) {
1766 agentx_log_axc_warnx(axc, "index %s: unexpected index type",
1767 ax_oid2string(&(axr->axr_oid)));
1768 axi->axi_cstate = AX_CSTATE_CLOSE;
1769 return -1;
1770 }
1771 if (ax_oid_cmp(&(resp->ap_varbindlist[0].avb_oid),
1772 &(axi->axi_vb.avb_oid)) != 0) {
1773 agentx_log_axc_warnx(axc, "index %s: unexpected oid",
1774 ax_oid2string(&(axr->axr_oid)));
1775 axi->axi_cstate = AX_CSTATE_CLOSE;
1776 return -1;
1777 }
1778
1779 switch (axi->axi_vb.avb_type) {
1780 case AX_DATA_TYPE_INTEGER:
1781 if (axi->axi_type == AXI_TYPE_NEW ||
1782 axi->axi_type == AXI_TYPE_ANY)
1783 axi->axi_vb.avb_data.avb_int32 =
1784 resp->ap_varbindlist[0].avb_data.avb_int32;
1785 else if (axi->axi_vb.avb_data.avb_int32 !=
1786 resp->ap_varbindlist[0].avb_data.avb_int32) {
1787 agentx_log_axc_warnx(axc, "index %s: unexpected "
1788 "index value", ax_oid2string(&(axr->axr_oid)));
1789 axi->axi_cstate = AX_CSTATE_CLOSE;
1790 return -1;
1791 }
1792 agentx_log_axc_info(axc, "index %s: allocated '%d'",
1793 ax_oid2string(&(axi->axi_vb.avb_oid)),
1794 axi->axi_vb.avb_data.avb_int32);
1795 break;
1796 default:
1797 agentx_log_axc_fatalx(axc, "%s: Unsupported index type",
1798 __func__);
1799 }
1800
1801 if (axi->axi_dstate == AX_DSTATE_CLOSE)
1802 return agentx_index_close(axi);
1803
1804 objects_start:
1805 /* TODO Make use of range_subid register */
1806 for (i = 0; i < axi->axi_objectlen; i++) {
1807 if (axi->axi_object[i]->axo_dstate == AX_DSTATE_OPEN) {
1808 if (agentx_object_start(axi->axi_object[i]) == -1)
1809 return -1;
1810 }
1811 }
1812 return 0;
1813}
1814
1815void
1816agentx_index_free(struct agentx_index *axi)
1817{
1818 size_t i;
1819 struct agentx_object *axo;
1820 struct agentx *ax;
1821 int axfree;
1822
1823 if (axi == NULL((void *)0))
1824 return;
1825
1826 ax = axi->axi_axr->axr_axc->axc_axs->axs_ax;
1827 axfree = ax->ax_free;
1828 ax->ax_free = 1;
1829
1830 if (axi->axi_dstate == AX_DSTATE_CLOSE)
1831 agentx_log_axc_fatalx(axi->axi_axr->axr_axc,
1832 "%s: double free", __func__);
1833
1834 /* TODO Do a range_subid unregister before freeing */
1835 for (i = 0; i < axi->axi_objectlen; i++) {
1836 axo = axi->axi_object[i];
1837 if (axo->axo_dstate != AX_DSTATE_CLOSE) {
1838 agentx_object_free(axo);
1839 if (axi->axi_object[i] != axo)
1840 i--;
1841 }
1842 }
1843
1844 axi->axi_dstate = AX_DSTATE_CLOSE;
1845
1846 if (axi->axi_cstate == AX_CSTATE_OPEN)
1847 (void) agentx_index_close(axi);
1848 if (!axfree)
1849 agentx_free_finalize(ax);
1850}
1851
1852static void
1853agentx_index_free_finalize(struct agentx_index *axi)
1854{
1855 struct agentx_region *axr = axi->axi_axr;
1856
1857 if (axi->axi_cstate != AX_CSTATE_CLOSE ||
1858 axi->axi_dstate != AX_DSTATE_CLOSE ||
1859 axi->axi_objectlen != 0)
1860 return;
1861
1862 TAILQ_REMOVE(&(axr->axr_indices), axi, axi_axr_indices)do { if (((axi)->axi_axr_indices.tqe_next) != ((void *)0))
(axi)->axi_axr_indices.tqe_next->axi_axr_indices.tqe_prev
= (axi)->axi_axr_indices.tqe_prev; else (&(axr->axr_indices
))->tqh_last = (axi)->axi_axr_indices.tqe_prev; *(axi)->
axi_axr_indices.tqe_prev = (axi)->axi_axr_indices.tqe_next
; ; ; } while (0)
;
1863 ax_varbind_free(&(axi->axi_vb));
1864 free(axi->axi_object);
1865 free(axi);
1866}
1867
1868static void
1869agentx_index_reset(struct agentx_index *axi)
1870{
1871 struct agentx *ax = axi->axi_axr->axr_axc->axc_axs->axs_ax;
1872
1873 axi->axi_cstate = AX_CSTATE_CLOSE;
1874
1875 if (!ax->ax_free)
1876 agentx_free_finalize(ax);
1877}
1878
1879static int
1880agentx_index_close(struct agentx_index *axi)
1881{
1882 struct agentx_region *axr = axi->axi_axr;
1883 struct agentx_context *axc = axr->axr_axc;
1884 struct agentx_session *axs = axc->axc_axs;
1885 struct agentx *ax = axs->axs_ax;
1886 uint32_t packetid;
1887
1888#ifdef AX_DEBUG
1889 if (axi->axi_cstate != AX_CSTATE_OPEN)
1890 agentx_log_axc_fatalx(axc,
1891 "%s: unexpected index deallocation", __func__);
1892#endif
1893
1894 axi->axi_cstate = AX_CSTATE_WAITCLOSE;
1895 if (axs->axs_cstate == AX_CSTATE_WAITCLOSE)
1896 return 0;
1897
1898 /* We might be able to bundle, but if we fail we'd have to reorganise */
1899 packetid = ax_indexdeallocate(ax->ax_ax, axs->axs_id,
1900 AGENTX_CONTEXT_CTX(axc)(axc->axc_name_default ? ((void *)0) : &(axc->axc_name
))
, &(axi->axi_vb), 1);
1901 if (packetid == 0) {
1902 agentx_log_axc_warn(axc, "couldn't generate %s",
1903 ax_pdutype2string(AX_PDU_TYPE_INDEXDEALLOCATE));
1904 agentx_reset(ax);
1905 return -1;
1906 }
1907 agentx_log_axc_info(axc, "index %s: deallocating",
1908 ax_oid2string(&(axi->axi_vb.avb_oid)));
1909 return agentx_request(ax, packetid, agentx_index_close_finalize,
1910 axi);
1911}
1912
1913static int
1914agentx_index_close_finalize(struct ax_pdu *pdu, void *cookie)
1915{
1916 struct agentx_index *axi = cookie;
1917 struct agentx_region *axr = axi->axi_axr;
1918 struct agentx_context *axc = axr->axr_axc;
1919 struct agentx_session *axs = axc->axc_axs;
1920 struct agentx *ax = axs->axs_ax;
1921 struct ax_pdu_response *resp = &(pdu->ap_payload.ap_response);
1922 int axfree = ax->ax_free;
1923
1924#ifdef AX_DEBUG
1925 if (axi->axi_cstate != AX_CSTATE_WAITCLOSE)
1926 agentx_log_axc_fatalx(axc, "%s: unexpected indexdeallocate",
1927 __func__);
1928#endif
1929
1930 if (pdu->ap_payload.ap_response.ap_error != AX_PDU_ERROR_NOERROR) {
1931 agentx_log_axc_warnx(axc,
1932 "index %s: couldn't deallocate: %s",
1933 ax_oid2string(&(axi->axi_vb.avb_oid)),
1934 ax_error2string(resp->ap_error));
1935 agentx_reset(ax);
1936 return -1;
1937 }
1938
1939 if (resp->ap_nvarbind != 1) {
1940 agentx_log_axc_warnx(axc,
1941 "index %s: unexpected number of indices",
1942 ax_oid2string(&(axr->axr_oid)));
1943 agentx_reset(ax);
1944 return -1;
1945 }
1946 if (resp->ap_varbindlist[0].avb_type != axi->axi_vb.avb_type) {
1947 agentx_log_axc_warnx(axc, "index %s: unexpected index type",
1948 ax_oid2string(&(axr->axr_oid)));
1949 agentx_reset(ax);
1950 return -1;
1951 }
1952 if (ax_oid_cmp(&(resp->ap_varbindlist[0].avb_oid),
1953 &(axi->axi_vb.avb_oid)) != 0) {
1954 agentx_log_axc_warnx(axc, "index %s: unexpected oid",
1955 ax_oid2string(&(axr->axr_oid)));
1956 agentx_reset(ax);
1957 return -1;
1958 }
1959 switch (axi->axi_vb.avb_type) {
1960 case AX_DATA_TYPE_INTEGER:
1961 if (axi->axi_vb.avb_data.avb_int32 !=
1962 resp->ap_varbindlist[0].avb_data.avb_int32) {
1963 agentx_log_axc_warnx(axc,
1964 "index %s: unexpected index value",
1965 ax_oid2string(&(axr->axr_oid)));
1966 agentx_reset(ax);
1967 return -1;
1968 }
1969 break;
1970 default:
1971 agentx_log_axc_fatalx(axc, "%s: Unsupported index type",
1972 __func__);
1973 }
1974
1975 axi->axi_cstate = AX_CSTATE_CLOSE;
1976 ax->ax_free = 1;
1977
1978 agentx_log_axc_info(axc, "index %s: deallocated",
1979 ax_oid2string(&(axi->axi_vb.avb_oid)));
1980
1981 if (axr->axr_cstate == AX_CSTATE_OPEN &&
1982 axi->axi_dstate == AX_DSTATE_OPEN)
1983 agentx_index_start(axi);
1984
1985 if (!axfree)
1986 agentx_free_finalize(ax);
1987 return 0;
1988}
1989
1990struct agentx_object *
1991agentx_object(struct agentx_region *axr, uint32_t oid[], size_t oidlen,
1992 struct agentx_index *axi[], size_t axilen, int implied,
1993 void (*get)(struct agentx_varbind *))
1994{
1995 struct agentx_object *axo, **taxo, axo_search;
1996 struct agentx_index *laxi;
1997 const char *errstr;
1998 int ready = 1;
1999 size_t i, j;
2000
2001 if (axr->axr_dstate == AX_DSTATE_CLOSE)
2002 agentx_log_axc_fatalx(axr->axr_axc, "%s: use after free",
2003 __func__);
2004 if (axilen > AGENTX_OID_INDEX_MAX_LEN10) {
2005#ifdef AX_DEBUG
2006 agentx_log_axc_fatalx(axr->axr_axc, "%s: indexlen > %d",
2007 __func__, AGENTX_OID_INDEX_MAX_LEN10);
2008#else
2009 agentx_log_axc_warnx(axr->axr_axc, "%s: indexlen > %d",
2010 __func__, AGENTX_OID_INDEX_MAX_LEN10);
2011 errno(*__errno()) = EINVAL22;
2012 return NULL((void *)0);
2013#endif
2014 }
2015
2016 if (agentx_oidfill(&(axo_search.axo_oid), oid, oidlen, &errstr) == -1) {
2017#ifdef AX_DEBUG
2018 agentx_log_axc_fatalx(axr->axr_axc, "%s: %s", __func__, errstr);
2019#else
2020 agentx_log_axc_warnx(axr->axr_axc, "%s: %s", __func__, errstr);
2021 return NULL((void *)0);
2022#endif
2023 }
2024
2025 do {
2026 if (RB_FIND(axc_objects, &(axr->axr_axc->axc_objects),axc_objects_RB_FIND(&(axr->axr_axc->axc_objects), &
axo_search)
2027 &axo_search)axc_objects_RB_FIND(&(axr->axr_axc->axc_objects), &
axo_search)
!= NULL((void *)0)) {
2028#ifdef AX_DEBUG
2029 agentx_log_axc_fatalx(axr->axr_axc, "%s: invalid "
2030 "parent child object relationship", __func__);
2031#else
2032 agentx_log_axc_warnx(axr->axr_axc, "%s: invalid "
2033 "parent child object relationship", __func__);
2034 errno(*__errno()) = EINVAL22;
2035 return NULL((void *)0);
2036#endif
2037 }
2038 axo_search.axo_oid.aoi_idlen--;
2039 } while (axo_search.axo_oid.aoi_idlen > 0);
2040 axo_search.axo_oid.aoi_idlen = oidlen;
2041 axo = RB_NFIND(axc_objects, &(axr->axr_axc->axc_objects), &axo_search)axc_objects_RB_NFIND(&(axr->axr_axc->axc_objects), &
axo_search)
;
2042 if (axo != NULL((void *)0) &&
2043 ax_oid_cmp(&(axo->axo_oid), &(axo_search.axo_oid)) == 2) {
2044#ifdef AX_DEBUG
2045 agentx_log_axc_fatalx(axr->axr_axc, "%s: invalid parent "
2046 "child object relationship", __func__);
2047#else
2048 agentx_log_axc_warnx(axr->axr_axc, "%s: invalid parent "
2049 "child object relationship", __func__);
2050 errno(*__errno()) = EINVAL22;
2051 return NULL((void *)0);
2052#endif
2053 }
2054 if (implied == 1) {
2055 laxi = axi[axilen - 1];
2056 if (laxi->axi_vb.avb_type == AX_DATA_TYPE_OCTETSTRING) {
2057 if (laxi->axi_vb.avb_data.avb_ostring.aos_slen != 0) {
2058#ifdef AX_DEBUG
2059 agentx_log_axc_fatalx(axr->axr_axc,
2060 "%s: implied can only be used on strings "
2061 "of dynamic length", __func__);
2062#else
2063 agentx_log_axc_warnx(axr->axr_axc,
2064 "%s: implied can only be used on strings "
2065 "of dynamic length", __func__);
2066 errno(*__errno()) = EINVAL22;
2067 return NULL((void *)0);
2068#endif
2069 }
2070 } else if (laxi->axi_vb.avb_type == AX_DATA_TYPE_OID) {
2071 if (laxi->axi_vb.avb_data.avb_oid.aoi_idlen != 0) {
2072#ifdef AX_DEBUG
2073 agentx_log_axc_fatalx(axr->axr_axc,
2074 "%s: implied can only be used on oids of "
2075 "dynamic length", __func__);
2076#else
2077 agentx_log_axc_warnx(axr->axr_axc,
2078 "%s: implied can only be used on oids of "
2079 "dynamic length", __func__);
2080 errno(*__errno()) = EINVAL22;
2081 return NULL((void *)0);
2082#endif
2083 }
2084 } else {
2085#ifdef AX_DEBUG
2086 agentx_log_axc_fatalx(axr->axr_axc, "%s: implied "
2087 "can only be set on oid and string indices",
2088 __func__);
2089#else
2090 agentx_log_axc_warnx(axr->axr_axc, "%s: implied can "
2091 "only be set on oid and string indices", __func__);
2092 errno(*__errno()) = EINVAL22;
2093 return NULL((void *)0);
2094#endif
2095 }
2096 }
2097
2098 ready = axr->axr_cstate == AX_CSTATE_OPEN;
2099 if ((axo = calloc(1, sizeof(*axo))) == NULL((void *)0))
2100 return NULL((void *)0);
2101 axo->axo_axr = axr;
2102 bcopy(&(axo_search.axo_oid), &(axo->axo_oid), sizeof(axo->axo_oid));
2103 for (i = 0; i < axilen; i++) {
2104 axo->axo_index[i] = axi[i];
2105 if (axi[i]->axi_objectlen == axi[i]->axi_objectsize) {
2106 taxo = recallocarray(axi[i]->axi_object,
2107 axi[i]->axi_objectlen, axi[i]->axi_objectlen + 1,
2108 sizeof(*axi[i]->axi_object));
2109 if (taxo == NULL((void *)0)) {
2110 free(axo);
2111 return NULL((void *)0);
2112 }
2113 axi[i]->axi_object = taxo;
2114 axi[i]->axi_objectsize = axi[i]->axi_objectlen + 1;
2115 }
2116 for (j = 0; j < axi[i]->axi_objectlen; j++) {
2117 if (ax_oid_cmp(&(axo->axo_oid),
2118 &(axi[i]->axi_object[j]->axo_oid)) < 0) {
2119 memmove(&(axi[i]->axi_object[j + 1]),
2120 &(axi[i]->axi_object[j]),
2121 sizeof(*(axi[i]->axi_object)) *
2122 (axi[i]->axi_objectlen - j));
2123 break;
2124 }
2125 }
2126 axi[i]->axi_object[j] = axo;
2127 axi[i]->axi_objectlen++;
2128 if (axi[i]->axi_cstate != AX_CSTATE_OPEN)
2129 ready = 0;
2130 }
2131 axo->axo_indexlen = axilen;
2132 axo->axo_implied = implied;
2133 axo->axo_timeout = 0;
2134 axo->axo_lock = 0;
2135 axo->axo_get = get;
2136 axo->axo_cstate = AX_CSTATE_CLOSE;
2137 axo->axo_dstate = AX_DSTATE_OPEN;
2138
2139 TAILQ_INSERT_TAIL(&(axr->axr_objects), axo, axo_axr_objects)do { (axo)->axo_axr_objects.tqe_next = ((void *)0); (axo)->
axo_axr_objects.tqe_prev = (&(axr->axr_objects))->tqh_last
; *(&(axr->axr_objects))->tqh_last = (axo); (&(
axr->axr_objects))->tqh_last = &(axo)->axo_axr_objects
.tqe_next; } while (0)
;
2140 RB_INSERT(axc_objects, &(axr->axr_axc->axc_objects), axo)axc_objects_RB_INSERT(&(axr->axr_axc->axc_objects),
axo)
;
2141
2142 if (ready)
2143 agentx_object_start(axo);
2144
2145 return axo;
2146}
2147
2148static int
2149agentx_object_start(struct agentx_object *axo)
2150{
2151 struct agentx_region *axr = axo->axo_axr;
2152 struct agentx_context *axc = axr->axr_axc;
2153 struct agentx_session *axs = axc->axc_axs;
2154 struct agentx *ax = axs->axs_ax;
2155 struct ax_oid oid;
2156 char oids[1024];
2157 size_t i;
2158 int needregister = 0;
2159 uint32_t packetid;
2160 uint8_t flags = AX_PDU_FLAG_INSTANCE_REGISTRATION(1 << 0);
2161
2162#ifdef AX_DEBUG
2163 if (axr->axr_cstate != AX_CSTATE_OPEN ||
2164 axo->axo_cstate != AX_CSTATE_CLOSE ||
2165 axo->axo_dstate != AX_DSTATE_OPEN)
2166 agentx_log_axc_fatalx(axc,
2167 "%s: unexpected object registration", __func__);
2168#endif
2169
2170 if (axo->axo_timeout != 0)
2171 needregister = 1;
2172 for (i = 0; i < axo->axo_indexlen; i++) {
2173 if (axo->axo_index[i]->axi_cstate != AX_CSTATE_OPEN)
2174 return 0;
2175 if (axo->axo_index[i]->axi_type != AXI_TYPE_DYNAMIC)
2176 needregister = 1;
2177 }
2178 if (!needregister) {
2179 axo->axo_cstate = AX_CSTATE_WAITOPEN;
2180 agentx_object_finalize(NULL((void *)0), axo);
2181 return 0;
2182 }
2183
2184 bcopy(&(axo->axo_oid), &(oid), sizeof(oid));
2185 for (i = 0; i < axo->axo_indexlen; i++) {
2186 if (axo->axo_index[i]->axi_type == AXI_TYPE_DYNAMIC) {
2187 flags = 0;
2188 break;
2189 }
2190#ifdef AX_DEBUG
2191 if (axo->axo_index[i]->axi_vb.avb_type !=
2192 AX_DATA_TYPE_INTEGER)
2193 agentx_log_axc_fatalx(axc,
2194 "%s: Unsupported allocated index type", __func__);
2195#endif
2196 oid.aoi_id[oid.aoi_idlen++] =
2197 axo->axo_index[i]->axi_vb.avb_data.avb_int32;
2198 }
2199 packetid = ax_register(ax->ax_ax, flags, axs->axs_id,
2200 AGENTX_CONTEXT_CTX(axc)(axc->axc_name_default ? ((void *)0) : &(axc->axc_name
))
, axo->axo_timeout,
2201 AX_PRIORITY_DEFAULT127, 0, &oid, 0);
2202 if (packetid == 0) {
2203 agentx_log_axc_warn(axc, "couldn't generate %s",
2204 ax_pdutype2string(AX_PDU_TYPE_REGISTER));
2205 agentx_reset(ax);
2206 return -1;
2207 }
2208 strlcpy(oids, ax_oid2string(&(axo->axo_oid)), sizeof(oids));
2209 agentx_log_axc_info(axc, "object %s (%s %s): opening",
2210 oids, flags ? "instance" : "region", ax_oid2string(&(oid)));
2211 axo->axo_cstate = AX_CSTATE_WAITOPEN;
2212 return agentx_request(ax, packetid, agentx_object_finalize, axo);
2213}
2214
2215static int
2216agentx_object_finalize(struct ax_pdu *pdu, void *cookie)
2217{
2218 struct agentx_object *axo = cookie;
2219 struct agentx_context *axc = axo->axo_axr->axr_axc;
2220 struct ax_oid oid;
2221 char oids[1024];
2222 size_t i;
2223 uint8_t flags = 1;
2224
2225#ifdef AX_DEBUG
2226 if (axo->axo_cstate != AX_CSTATE_WAITOPEN)
2227 agentx_log_axc_fatalx(axc, "%s: not expecting object open",
2228 __func__);
2229#endif
2230
2231 if (pdu == NULL((void *)0)) {
2232 axo->axo_cstate = AX_CSTATE_OPEN;
2233 return 0;
2234 }
2235
2236 bcopy(&(axo->axo_oid), &oid, sizeof(oid));
2237 for (i = 0; i < axo->axo_indexlen; i++) {
2238 if (axo->axo_index[i]->axi_type == AXI_TYPE_DYNAMIC) {
2239 flags = 0;
2240 break;
2241 }
2242#ifdef AX_DEBUG
2243 if (axo->axo_index[i]->axi_vb.avb_type !=
2244 AX_DATA_TYPE_INTEGER)
2245 agentx_log_axc_fatalx(axc,
2246 "%s: Unsupported allocated index type", __func__);
2247#endif
2248
2249 oid.aoi_id[oid.aoi_idlen++] =
2250 axo->axo_index[i]->axi_vb.avb_data.avb_int32;
2251 }
2252 strlcpy(oids, ax_oid2string(&(axo->axo_oid)), sizeof(oids));
2253
2254 /*
2255 * We should only be here for table objects with registered indices.
2256 * If we fail here something is misconfigured and the admin should fix
2257 * it.
2258 */
2259 if (pdu->ap_payload.ap_response.ap_error != AX_PDU_ERROR_NOERROR) {
2260 axo->axo_cstate = AX_CSTATE_CLOSE;
2261 agentx_log_axc_info(axc, "object %s (%s %s): %s",
2262 oids, flags ? "instance" : "region", ax_oid2string(&oid),
2263 ax_error2string(pdu->ap_payload.ap_response.ap_error));
2264 return 0;
2265 }
2266 axo->axo_cstate = AX_CSTATE_OPEN;
2267 agentx_log_axc_info(axc, "object %s (%s %s): open", oids,
2268 flags ? "instance" : "region", ax_oid2string(&oid));
2269
2270 if (axo->axo_dstate == AX_DSTATE_CLOSE)
2271 return agentx_object_close(axo);
2272
2273 return 0;
2274}
2275
2276static int
2277agentx_object_lock(struct agentx_object *axo)
2278{
2279 if (axo->axo_lock == UINT32_MAX0xffffffffU) {
2280 agentx_log_axc_warnx(axo->axo_axr->axr_axc,
2281 "%s: axo_lock == %u", __func__, UINT32_MAX0xffffffffU);
2282 return -1;
2283 }
2284 axo->axo_lock++;
2285 return 0;
2286}
2287
2288static void
2289agentx_object_unlock(struct agentx_object *axo)
2290{
2291 struct agentx *ax = axo->axo_axr->axr_axc->axc_axs->axs_ax;
2292
2293#ifdef AX_DEBUG
2294 if (axo->axo_lock == 0)
2295 agentx_log_axc_fatalx(axo->axo_axr->axr_axc,
2296 "%s: axo_lock == 0", __func__);
2297#endif
2298 axo->axo_lock--;
2299 if (axo->axo_lock == 0) {
2300 if (!ax->ax_free)
2301 agentx_free_finalize(ax);
2302 }
2303}
2304
2305static int
2306agentx_object_close(struct agentx_object *axo)
2307{
2308 struct agentx_context *axc = axo->axo_axr->axr_axc;
2309 struct agentx_session *axs = axc->axc_axs;
2310 struct agentx *ax = axs->axs_ax;
2311 struct ax_oid oid;
2312 char oids[1024];
2313 size_t i;
2314 int needclose = 0;
2315 uint32_t packetid;
2316 uint8_t flags = 1;
2317
2318#ifdef AX_DEBUG
2319 if (axo->axo_cstate != AX_CSTATE_OPEN)
2320 agentx_log_axc_fatalx(axc, "%s: unexpected object close",
2321 __func__);
2322#endif
2323
2324 for (i = 0; i < axo->axo_indexlen; i++) {
2325#ifdef AX_DEBUG
2326 if (axo->axo_index[i]->axi_cstate != AX_CSTATE_OPEN)
2327 agentx_log_axc_fatalx(axc,
2328 "%s: Object open while index closed", __func__);
2329#endif
2330 if (axo->axo_index[i]->axi_type != AXI_TYPE_DYNAMIC)
2331 needclose = 1;
2332 }
2333 axo->axo_cstate = AX_CSTATE_WAITCLOSE;
2334 if (axs->axs_cstate == AX_CSTATE_WAITCLOSE)
2335 return 0;
2336 if (!needclose) {
2337 agentx_object_close_finalize(NULL((void *)0), axo);
2338 return 0;
2339 }
2340
2341 bcopy(&(axo->axo_oid), &(oid), sizeof(oid));
2342 for (i = 0; i < axo->axo_indexlen; i++) {
2343 if (axo->axo_index[i]->axi_type == AXI_TYPE_DYNAMIC) {
2344 flags = 0;
2345 break;
2346 }
2347#ifdef AX_DEBUG
2348 if (axo->axo_index[i]->axi_vb.avb_type !=
2349 AX_DATA_TYPE_INTEGER)
2350 agentx_log_axc_fatalx(axc,
2351 "%s: Unsupported allocated index type", __func__);
2352#endif
2353 oid.aoi_id[oid.aoi_idlen++] =
2354 axo->axo_index[i]->axi_vb.avb_data.avb_int32;
2355 }
2356 packetid = ax_unregister(ax->ax_ax, axs->axs_id,
2357 AGENTX_CONTEXT_CTX(axc)(axc->axc_name_default ? ((void *)0) : &(axc->axc_name
))
, AX_PRIORITY_DEFAULT127, 0, &oid, 0);
2358 if (packetid == 0) {
2359 agentx_log_axc_warn(axc, "couldn't generate %s",
2360 ax_pdutype2string(AX_PDU_TYPE_UNREGISTER));
2361 agentx_reset(ax);
2362 return -1;
2363 }
2364 strlcpy(oids, ax_oid2string(&(axo->axo_oid)), sizeof(oids));
2365 agentx_log_axc_info(axc, "object %s (%s %s): closing",
2366 oids, flags ? "instance" : "region", ax_oid2string(&(oid)));
2367 return agentx_request(ax, packetid, agentx_object_close_finalize,
2368 axo);
2369}
2370
2371static int
2372agentx_object_close_finalize(struct ax_pdu *pdu, void *cookie)
2373{
2374 struct agentx_object *axo = cookie;
2375 struct agentx_region *axr = axo->axo_axr;
2376 struct agentx_context *axc = axr->axr_axc;
2377 struct agentx_session *axs = axc->axc_axs;
2378 struct agentx *ax = axs->axs_ax;
2379 struct ax_oid oid;
2380 char oids[1024];
2381 uint8_t flags = 1;
2382 size_t i;
2383 int axfree = ax->ax_free;
2384
2385#ifdef AX_DEBUG
2386 if (axo->axo_cstate != AX_CSTATE_WAITCLOSE)
2387 agentx_log_axc_fatalx(axc,
2388 "%s: unexpected object unregister", __func__);
2389#endif
2390
2391 if (pdu != NULL((void *)0)) {
2392 bcopy(&(axo->axo_oid), &(oid), sizeof(oid));
2393 for (i = 0; i < axo->axo_indexlen; i++) {
2394 if (axo->axo_index[i]->axi_type == AXI_TYPE_DYNAMIC) {
2395 flags = 0;
2396 break;
2397 }
2398#ifdef AX_DEBUG
2399 if (axo->axo_index[i]->axi_vb.avb_type !=
2400 AX_DATA_TYPE_INTEGER)
2401 agentx_log_axc_fatalx(axc,
2402 "%s: Unsupported allocated index type",
2403 __func__);
2404#endif
2405 oid.aoi_id[oid.aoi_idlen++] =
2406 axo->axo_index[i]->axi_vb.avb_data.avb_int32;
2407 }
2408 strlcpy(oids, ax_oid2string(&(axo->axo_oid)), sizeof(oids));
2409 if (pdu->ap_payload.ap_response.ap_error !=
2410 AX_PDU_ERROR_NOERROR) {
2411 agentx_log_axc_warnx(axc,
2412 "closing object %s (%s %s): %s", oids,
2413 flags ? "instance" : "region",
2414 ax_oid2string(&oid), ax_error2string(
2415 pdu->ap_payload.ap_response.ap_error));
2416 agentx_reset(ax);
2417 return -1;
2418 }
2419 agentx_log_axc_info(axc, "object %s (%s %s): closed", oids,
2420 flags ? "instance" : "region", ax_oid2string(&oid));
2421 }
2422
2423 ax->ax_free = 1;
2424 if (axr->axr_cstate == AX_CSTATE_OPEN &&
2425 axo->axo_dstate == AX_DSTATE_OPEN)
2426 agentx_object_start(axo);
2427
2428 if (!axfree)
2429 agentx_free_finalize(ax);
2430
2431 return 0;
2432}
2433
2434void
2435agentx_object_free(struct agentx_object *axo)
2436{
2437 struct agentx *ax;
2438 int axfree;
2439
2440 if (axo == NULL((void *)0))
2441 return;
2442
2443 ax = axo->axo_axr->axr_axc->axc_axs->axs_ax;
2444 axfree = ax->ax_free;
2445 ax->ax_free = 1;
2446
2447 if (axo->axo_dstate == AX_DSTATE_CLOSE)
2448 agentx_log_axc_fatalx(axo->axo_axr->axr_axc,
2449 "%s: double free", __func__);
2450
2451 axo->axo_dstate = AX_DSTATE_CLOSE;
2452
2453 if (axo->axo_cstate == AX_CSTATE_OPEN)
2454 agentx_object_close(axo);
2455 if (!axfree)
2456 agentx_free_finalize(ax);
2457}
2458
2459static void
2460agentx_object_free_finalize(struct agentx_object *axo)
2461{
2462#ifdef AX_DEBUG
2463 struct agentx *ax = axo->axo_axr->axr_axc->axc_axs->axs_ax;
2464#endif
2465 size_t i, j;
2466 int found;
2467
2468 if (axo->axo_dstate != AX_DSTATE_CLOSE ||
2469 axo->axo_cstate != AX_CSTATE_CLOSE ||
2470 axo->axo_lock != 0)
2471 return;
2472
2473 RB_REMOVE(axc_objects, &(axo->axo_axr->axr_axc->axc_objects), axo)axc_objects_RB_REMOVE(&(axo->axo_axr->axr_axc->axc_objects
), axo)
;
2474 TAILQ_REMOVE(&(axo->axo_axr->axr_objects), axo, axo_axr_objects)do { if (((axo)->axo_axr_objects.tqe_next) != ((void *)0))
(axo)->axo_axr_objects.tqe_next->axo_axr_objects.tqe_prev
= (axo)->axo_axr_objects.tqe_prev; else (&(axo->axo_axr
->axr_objects))->tqh_last = (axo)->axo_axr_objects.tqe_prev
; *(axo)->axo_axr_objects.tqe_prev = (axo)->axo_axr_objects
.tqe_next; ; ; } while (0)
;
2475
2476 for (i = 0; i < axo->axo_indexlen; i++) {
2477 found = 0;
2478 for (j = 0; j < axo->axo_index[i]->axi_objectlen; j++) {
2479 if (axo->axo_index[i]->axi_object[j] == axo)
2480 found = 1;
2481 if (found && j + 1 != axo->axo_index[i]->axi_objectlen)
2482 axo->axo_index[i]->axi_object[j] =
2483 axo->axo_index[i]->axi_object[j + 1];
2484 }
2485#ifdef AX_DEBUG
2486 if (!found)
2487 agentx_log_axc_fatalx(axo->axo_axr->axr_axc,
2488 "%s: object not found in index", __func__);
2489#endif
2490 axo->axo_index[i]->axi_objectlen--;
2491 }
2492
2493 free(axo);
2494}
2495
2496static void
2497agentx_object_reset(struct agentx_object *axo)
2498{
2499 struct agentx *ax = axo->axo_axr->axr_axc->axc_axs->axs_ax;
2500
2501 axo->axo_cstate = AX_CSTATE_CLOSE;
2502
2503 if (!ax->ax_free)
2504 agentx_free_finalize(ax);
2505}
2506
2507static int
2508agentx_object_cmp(struct agentx_object *o1, struct agentx_object *o2)
2509{
2510 return ax_oid_cmp(&(o1->axo_oid), &(o2->axo_oid));
2511}
2512
2513static int
2514agentx_object_implied(struct agentx_object *axo,
2515 struct agentx_index *axi)
2516{
2517 size_t i = 0;
2518 struct ax_varbind *vb;
2519
2520 for (i = 0; i < axo->axo_indexlen; i++) {
2521 if (axo->axo_index[i] == axi) {
2522 vb = &axi->axi_vb;
2523 if (vb->avb_type == AX_DATA_TYPE_OCTETSTRING &&
2524 vb->avb_data.avb_ostring.aos_slen != 0)
2525 return 1;
2526 else if (vb->avb_type == AX_DATA_TYPE_OID &&
2527 vb->avb_data.avb_oid.aoi_idlen != 0)
2528 return 1;
2529 else if (i == axo->axo_indexlen - 1)
2530 return axo->axo_implied;
2531 return 0;
2532 }
2533 }
2534#ifdef AX_DEBUG
2535 agentx_log_axc_fatalx(axo->axo_axr->axr_axc, "%s: unsupported index",
2536 __func__);
2537#endif
2538 return 0;
2539}
2540
2541static void
2542agentx_get_start(struct agentx_context *axc, struct ax_pdu *pdu)
2543{
2544 struct agentx_session *axs = axc->axc_axs;
2545 struct agentx *ax = axs->axs_ax;
2546 struct agentx_get *axg, taxg;
2547 struct ax_pdu_searchrangelist *srl;
2548 char *logmsg = NULL((void *)0);
2549 size_t i, j;
2550 int fail = 0;
2551
2552 if ((axg = calloc(1, sizeof(*axg))) == NULL((void *)0)) {
2553 taxg.axg_sessionid = pdu->ap_header.aph_sessionid;
2554 taxg.axg_transactionid = pdu->ap_header.aph_transactionid;
2555 taxg.axg_packetid = pdu->ap_header.aph_packetid;
2556 taxg.axg_context_default = axc->axc_name_default;
2557 taxg.axg_fd = axc->axc_axs->axs_ax->ax_fd;
2558 agentx_log_axg_warn(&taxg, "Couldn't parse request");
2559 agentx_reset(ax);
2560 return;
2561 }
2562
2563 axg->axg_sessionid = pdu->ap_header.aph_sessionid;
2564 axg->axg_transactionid = pdu->ap_header.aph_transactionid;
2565 axg->axg_packetid = pdu->ap_header.aph_packetid;
2566 axg->axg_context_default = axc->axc_name_default;
2567 axg->axg_fd = axc->axc_axs->axs_ax->ax_fd;
2568 if (!axc->axc_name_default) {
2569 axg->axg_context.aos_string =
2570 (unsigned char *)strdup((char *)axc->axc_name.aos_string);
2571 if (axg->axg_context.aos_string == NULL((void *)0)) {
2572 agentx_log_axg_warn(axg, "Couldn't parse request");
2573 free(axg);
2574 agentx_reset(ax);
2575 return;
2576 }
2577 }
2578 axg->axg_context.aos_slen = axc->axc_name.aos_slen;
2579 axg->axg_type = pdu->ap_header.aph_type;
2580 axg->axg_axc = axc;
2581 TAILQ_INSERT_TAIL(&(ax->ax_getreqs), axg, axg_ax_getreqs)do { (axg)->axg_ax_getreqs.tqe_next = ((void *)0); (axg)->
axg_ax_getreqs.tqe_prev = (&(ax->ax_getreqs))->tqh_last
; *(&(ax->ax_getreqs))->tqh_last = (axg); (&(ax
->ax_getreqs))->tqh_last = &(axg)->axg_ax_getreqs
.tqe_next; } while (0)
;
2582 if (axg->axg_type == AX_PDU_TYPE_GET ||
2583 axg->axg_type == AX_PDU_TYPE_GETNEXT) {
2584 srl = &(pdu->ap_payload.ap_srl);
2585 axg->axg_nvarbind = srl->ap_nsr;
2586 } else {
2587 axg->axg_nonrep = pdu->ap_payload.ap_getbulk.ap_nonrep;
2588 axg->axg_maxrep = pdu->ap_payload.ap_getbulk.ap_maxrep;
2589 srl = &(pdu->ap_payload.ap_getbulk.ap_srl);
2590 axg->axg_nvarbind = ((srl->ap_nsr - axg->axg_nonrep) *
2591 axg->axg_maxrep) + axg->axg_nonrep;
2592 }
2593
2594 if ((axg->axg_varbind = calloc(axg->axg_nvarbind,
2595 sizeof(*(axg->axg_varbind)))) == NULL((void *)0)) {
2596 agentx_log_axg_warn(axg, "Couldn't parse request");
2597 agentx_get_free(axg);
2598 agentx_reset(ax);
2599 return;
2600 }
2601
2602 /* XXX net-snmp doesn't use getbulk, so untested */
2603 /* Two loops: varbind after needs to be initialized */
2604 for (i = 0; i < srl->ap_nsr; i++) {
2605 if (i < axg->axg_nonrep ||
2606 axg->axg_type != AX_PDU_TYPE_GETBULK)
2607 j = i;
2608 else if (axg->axg_maxrep == 0)
2609 break;
2610 else
2611 j = (axg->axg_maxrep * i) + axg->axg_nonrep;
2612 bcopy(&(srl->ap_sr[i].asr_start),
2613 &(axg->axg_varbind[j].axv_vb.avb_oid),
2614 sizeof(srl->ap_sr[i].asr_start));
2615 bcopy(&(srl->ap_sr[i].asr_start),
2616 &(axg->axg_varbind[j].axv_start),
2617 sizeof(srl->ap_sr[i].asr_start));
2618 bcopy(&(srl->ap_sr[i].asr_stop),
2619 &(axg->axg_varbind[j].axv_end),
2620 sizeof(srl->ap_sr[i].asr_stop));
2621 axg->axg_varbind[j].axv_initialized = 1;
2622 axg->axg_varbind[j].axv_axg = axg;
2623 axg->axg_varbind[j].axv_include =
2624 srl->ap_sr[i].asr_start.aoi_include;
2625 if (j == 0)
2626 fail |= agentx_strcat(&logmsg, " {");
2627 else
2628 fail |= agentx_strcat(&logmsg, ",{");
2629 fail |= agentx_strcat(&logmsg,
2630 ax_oid2string(&(srl->ap_sr[i].asr_start)));
2631 if (srl->ap_sr[i].asr_start.aoi_include)
2632 fail |= agentx_strcat(&logmsg, " (inclusive)");
2633 if (srl->ap_sr[i].asr_stop.aoi_idlen != 0) {
2634 fail |= agentx_strcat(&logmsg, " - ");
2635 fail |= agentx_strcat(&logmsg,
2636 ax_oid2string(&(srl->ap_sr[i].asr_stop)));
2637 }
2638 fail |= agentx_strcat(&logmsg, "}");
2639 if (fail) {
2640 agentx_log_axg_warn(axg, "Couldn't parse request");
2641 free(logmsg);
2642 agentx_get_free(axg);
2643 agentx_reset(ax);
2644 return;
2645 }
2646 }
2647
2648 agentx_log_axg_debug(axg, "%s:%s",
2649 ax_pdutype2string(axg->axg_type), logmsg);
2650 free(logmsg);
2651
2652 for (i = 0; i < srl->ap_nsr; i++) {
2653 if (i < axg->axg_nonrep ||
2654 axg->axg_type != AX_PDU_TYPE_GETBULK)
2655 j = i;
2656 else if (axg->axg_maxrep == 0)
2657 break;
2658 else
2659 j = (axg->axg_maxrep * i) + axg->axg_nonrep;
2660 agentx_varbind_start(&(axg->axg_varbind[j]));
2661 }
2662}
2663
2664static void
2665agentx_get_finalize(struct agentx_get *axg)
2666{
2667 struct agentx_context *axc = axg->axg_axc;
2668 struct agentx_session *axs;
2669 struct agentx *ax;
2670 size_t i, j, nvarbind = 0;
2671 uint16_t error = 0, index = 0;
2672 struct ax_varbind *vbl;
2673 char *logmsg = NULL((void *)0);
2674 int fail = 0;
2675
2676 for (i = 0; i < axg->axg_nvarbind; i++) {
2677 if (axg->axg_varbind[i].axv_initialized) {
2678 if (axg->axg_varbind[i].axv_vb.avb_type == 0)
2679 return;
2680 nvarbind++;
2681 }
2682 }
2683
2684 if (axc == NULL((void *)0)) {
2685 agentx_get_free(axg);
2686 return;
2687 }
2688
2689 axs = axc->axc_axs;
2690 ax = axs->axs_ax;
2691
2692 if ((vbl = calloc(nvarbind, sizeof(*vbl))) == NULL((void *)0)) {
2693 agentx_log_axg_warn(axg, "Couldn't parse request");
2694 agentx_get_free(axg);
2695 agentx_reset(ax);
2696 return;
2697 }
2698 for (i = 0, j = 0; i < axg->axg_nvarbind; i++) {
2699 if (axg->axg_varbind[i].axv_initialized) {
2700 memcpy(&(vbl[j]), &(axg->axg_varbind[i].axv_vb),
2701 sizeof(*vbl));
2702 if (error == 0 && axg->axg_varbind[i].axv_error !=
2703 AX_PDU_ERROR_NOERROR) {
2704 error = axg->axg_varbind[i].axv_error;
2705 index = j + 1;
2706 }
2707 if (j == 0)
2708 fail |= agentx_strcat(&logmsg, " {");
2709 else
2710 fail |= agentx_strcat(&logmsg, ",{");
2711 fail |= agentx_strcat(&logmsg,
2712 ax_varbind2string(&(vbl[j])));
2713 if (axg->axg_varbind[i].axv_error !=
2714 AX_PDU_ERROR_NOERROR) {
2715 fail |= agentx_strcat(&logmsg, "(");
2716 fail |= agentx_strcat(&logmsg,
2717 ax_error2string(
2718 axg->axg_varbind[i].axv_error));
2719 fail |= agentx_strcat(&logmsg, ")");
2720 }
2721 fail |= agentx_strcat(&logmsg, "}");
2722 if (fail) {
2723 agentx_log_axg_warn(axg,
2724 "Couldn't parse request");
2725 free(logmsg);
2726 agentx_get_free(axg);
2727 return;
2728 }
2729 j++;
2730 }
2731 }
2732 agentx_log_axg_debug(axg, "response:%s", logmsg);
2733 free(logmsg);
2734
2735 if (ax_response(ax->ax_ax, axs->axs_id, axg->axg_transactionid,
2736 axg->axg_packetid, 0, error, index, vbl, nvarbind) == -1) {
2737 agentx_log_axg_warn(axg, "Couldn't parse request");
2738 agentx_reset(ax);
2739 } else
2740 agentx_wantwrite(ax, ax->ax_fd);
2741 free(vbl);
2742 agentx_get_free(axg);
2743}
2744
2745void
2746agentx_get_free(struct agentx_get *axg)
2747{
2748 struct agentx_varbind *axv;
2749 struct agentx_object *axo;
2750 struct agentx *ax;
2751 struct agentx_varbind_index *index;
2752 size_t i, j;
2753
2754 if (axg->axg_axc != NULL((void *)0)) {
2755 ax = axg->axg_axc->axc_axs->axs_ax;
2756 TAILQ_REMOVE(&(ax->ax_getreqs), axg, axg_ax_getreqs)do { if (((axg)->axg_ax_getreqs.tqe_next) != ((void *)0)) (
axg)->axg_ax_getreqs.tqe_next->axg_ax_getreqs.tqe_prev =
(axg)->axg_ax_getreqs.tqe_prev; else (&(ax->ax_getreqs
))->tqh_last = (axg)->axg_ax_getreqs.tqe_prev; *(axg)->
axg_ax_getreqs.tqe_prev = (axg)->axg_ax_getreqs.tqe_next; ;
; } while (0)
;
2757 }
2758
2759 for (i = 0; i < axg->axg_nvarbind; i++) {
2760 axv = &(axg->axg_varbind[i]);
2761 for (j = 0; axv->axv_axo != NULL((void *)0) &&
2762 j < axv->axv_axo->axo_indexlen; j++) {
2763 axo = axv->axv_axo;
2764 index = &(axv->axv_index[j]);
2765 if (axo->axo_index[j]->axi_vb.avb_type ==
2766 AX_DATA_TYPE_OCTETSTRING ||
2767 axo->axo_index[j]->axi_vb.avb_type ==
2768 AX_DATA_TYPE_IPADDRESS)
2769 free(index->axv_idata.avb_ostring.aos_string);
2770 }
2771 ax_varbind_free(&(axg->axg_varbind[i].axv_vb));
2772 }
2773
2774 free(axg->axg_context.aos_string);
2775 free(axg->axg_varbind);
2776 free(axg);
2777}
2778
2779static void
2780agentx_varbind_start(struct agentx_varbind *axv)
2781{
2782 struct agentx_get *axg = axv->axv_axg;
2783 struct agentx_context *axc = axg->axg_axc;
2784 struct agentx_object *axo, axo_search;
2785 struct agentx_varbind_index *index;
2786 struct ax_oid *oid;
2787 union ax_data *data;
2788 struct in_addr *ipaddress;
2789 unsigned char *ipbytes;
2790 size_t i, j, k;
2791 int overflow = 0, dynamic;
2792
2793#ifdef AX_DEBUG
2794 if (!axv->axv_initialized)
2795 agentx_log_axg_fatalx(axv->axv_axg,
2796 "%s: axv_initialized not set", __func__);
2797#endif
2798
2799 if (axc == NULL((void *)0)) {
2800 agentx_varbind_error_type(axv, AX_PDU_ERROR_PROCESSINGERROR, 1);
2801 return;
2802 }
2803
2804 bcopy(&(axv->axv_vb.avb_oid), &(axo_search.axo_oid),
2805 sizeof(axo_search.axo_oid));
2806
2807 do {
2808 axo = RB_FIND(axc_objects, &(axc->axc_objects), &axo_search)axc_objects_RB_FIND(&(axc->axc_objects), &axo_search
)
;
2809 if (axo_search.axo_oid.aoi_idlen > 0)
2810 axo_search.axo_oid.aoi_idlen--;
2811 } while (axo == NULL((void *)0) && axo_search.axo_oid.aoi_idlen > 0);
2812 if (axo == NULL((void *)0) || axo->axo_cstate != AX_CSTATE_OPEN) {
2813 axv->axv_include = 1;
2814 if (axv->axv_axg->axg_type == AX_PDU_TYPE_GET) {
2815 agentx_varbind_nosuchobject(axv);
2816 return;
2817 }
2818 bcopy(&(axv->axv_vb.avb_oid), &(axo_search.axo_oid),
2819 sizeof(axo_search.axo_oid));
2820 axo = RB_NFIND(axc_objects, &(axc->axc_objects), &axo_search)axc_objects_RB_NFIND(&(axc->axc_objects), &axo_search
)
;
2821getnext:
2822 while (axo != NULL((void *)0) && axo->axo_cstate != AX_CSTATE_OPEN)
2823 axo = RB_NEXT(axc_objects, &(axc->axc_objects), axo)axc_objects_RB_NEXT(axo);
2824 if (axo == NULL((void *)0) ||
2825 ax_oid_cmp(&(axo->axo_oid), &(axv->axv_end)) >= 0) {
2826 agentx_varbind_endofmibview(axv);
2827 return;
2828 }
2829 bcopy(&(axo->axo_oid), &(axv->axv_vb.avb_oid),
2830 sizeof(axo->axo_oid));
2831 }
2832 axv->axv_axo = axo;
2833 axv->axv_indexlen = axo->axo_indexlen;
2834 if (agentx_object_lock(axo) == -1) {
2835 agentx_varbind_error_type(axv,
2836 AX_PDU_ERROR_PROCESSINGERROR, 1);
2837 return;
2838 }
2839
2840 oid = &(axv->axv_vb.avb_oid);
2841 if (axo->axo_indexlen == 0) {
2842 if (axv->axv_axg->axg_type == AX_PDU_TYPE_GET) {
2843 if (oid->aoi_idlen != axo->axo_oid.aoi_idlen + 1 ||
2844 oid->aoi_id[oid->aoi_idlen - 1] != 0) {
2845 agentx_varbind_nosuchinstance(axv);
2846 return;
2847 }
2848 } else {
2849 if (oid->aoi_idlen == axo->axo_oid.aoi_idlen) {
2850 oid->aoi_id[oid->aoi_idlen++] = 0;
2851 axv->axv_include = 1;
2852 } else {
2853 axv->axv_axo = NULL((void *)0);
2854 agentx_object_unlock(axo);
2855 axo = RB_NEXT(axc_objects, &(axc->axc_objects),axc_objects_RB_NEXT(axo)
2856 axo)axc_objects_RB_NEXT(axo);
2857 goto getnext;
2858 }
2859 }
2860 j = oid->aoi_idlen;
2861 } else
2862 j = axo->axo_oid.aoi_idlen;
2863/*
2864 * We can't trust what the client gives us, so sometimes we need to map it to
2865 * index type.
2866 * - AX_PDU_TYPE_GET: we always return AX_DATA_TYPE_NOSUCHINSTANCE
2867 * - AX_PDU_TYPE_GETNEXT:
2868 * - Missing OID digits to match indices or !dynamic indices
2869 * (AX_DATA_TYPE_INTEGER) underflows will result in the following indices to
2870 * be NUL-initialized and the request type will be set to
2871 * AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE
2872 * - An overflow can happen on AX_DATA_TYPE_OCTETSTRING and
2873 * AX_DATA_TYPE_IPADDRESS data, and AX_DATA_TYPE_OCTETSTRING and
2874 * AX_DATA_TYPE_OID length. This results in request type being set to
2875 * AGENTX_REQUEST_TYPE_GETNEXT and will set the index to its maximum
2876 * value:
2877 * - AX_DATA_TYPE_INTEGER: UINT32_MAX
2878 * - AX_DATA_TYPE_OCTETSTRING: aos_slen = UINT32_MAX and
2879 * aos_string = NULL
2880 * - AX_DATA_TYPE_OID: aoi_idlen = UINT32_MAX and aoi_id[x] = UINT32_MAX
2881 * - AX_DATA_TYPE_IPADDRESS: 255.255.255.255
2882 */
2883 for (dynamic = 0, i = 0; i < axo->axo_indexlen; i++, j++) {
2884 index = &(axv->axv_index[i]);
2885 index->axv_axi = axo->axo_index[i];
2886 data = &(index->axv_idata);
2887 if (axo->axo_index[i]->axi_type == AXI_TYPE_DYNAMIC)
2888 dynamic = 1;
2889 switch (axo->axo_index[i]->axi_vb.avb_type) {
2890 case AX_DATA_TYPE_INTEGER:
2891 if (index->axv_axi->axi_type != AXI_TYPE_DYNAMIC) {
2892 index->axv_idata.avb_int32 =
2893 index->axv_axi->axi_vb.avb_data.avb_int32;
2894 if (overflow == 0) {
2895 if ((uint32_t)index->axv_idata.avb_int32 >
2896 oid->aoi_id[j])
2897 overflow = -1;
2898 else if ((uint32_t)index->axv_idata.avb_int32 <
2899 oid->aoi_id[j])
2900 overflow = 1;
2901 }
2902 } else if (overflow == 1)
2903 index->axv_idata.avb_int32 = INT32_MAX0x7fffffff;
2904 else if (j >= oid->aoi_idlen || overflow == -1)
2905 index->axv_idata.avb_int32 = 0;
2906 else {
2907 if (oid->aoi_id[j] > INT32_MAX0x7fffffff) {
2908 index->axv_idata.avb_int32 = INT32_MAX0x7fffffff;
2909 overflow = 1;
2910 } else
2911 index->axv_idata.avb_int32 =
2912 oid->aoi_id[j];
2913 }
2914 break;
2915 case AX_DATA_TYPE_OCTETSTRING:
2916 if (overflow == 1) {
2917 data->avb_ostring.aos_slen = UINT32_MAX0xffffffffU;
2918 data->avb_ostring.aos_string = NULL((void *)0);
2919 continue;
2920 } else if (j >= oid->aoi_idlen || overflow == -1) {
2921 data->avb_ostring.aos_slen = 0;
2922 data->avb_ostring.aos_string = NULL((void *)0);
2923 continue;
2924 }
2925 if (agentx_object_implied(axo, index->axv_axi))
2926 data->avb_ostring.aos_slen = oid->aoi_idlen - j;
2927 else {
2928 data->avb_ostring.aos_slen = oid->aoi_id[j++];
2929 if (data->avb_ostring.aos_slen >=
2930 AGENTX_OID_MAX_LEN128 - j) {
2931 data->avb_ostring.aos_slen = UINT32_MAX0xffffffffU;
2932 overflow = 1;
2933 }
2934 }
2935 if (data->avb_ostring.aos_slen == UINT32_MAX0xffffffffU ||
2936 data->avb_ostring.aos_slen == 0) {
2937 data->avb_ostring.aos_string = NULL((void *)0);
2938 continue;
2939 }
2940 data->avb_ostring.aos_string =
2941 malloc(data->avb_ostring.aos_slen + 1);
2942 if (data->avb_ostring.aos_string == NULL((void *)0)) {
2943 agentx_log_axg_warn(axg,
2944 "Failed to bind string index");
2945 agentx_varbind_error_type(axv,
2946 AX_PDU_ERROR_PROCESSINGERROR, 1);
2947 return;
2948 }
2949 for (k = 0; k < data->avb_ostring.aos_slen; k++, j++) {
2950 if (j < oid->aoi_idlen && oid->aoi_id[j] > 0xff)
2951 overflow = 1;
2952 if (overflow == 1)
2953 data->avb_ostring.aos_string[k] = 0xff;
2954 else if (j >= oid->aoi_idlen || overflow == -1)
2955 data->avb_ostring.aos_string[k] = '\0';
2956 else
2957 data->avb_ostring.aos_string[k] =
2958 oid->aoi_id[j];
2959 }
2960 data->avb_ostring.aos_string[k] = '\0';
2961 j--;
2962 break;
2963 case AX_DATA_TYPE_OID:
2964 if (overflow == 1) {
2965 data->avb_oid.aoi_idlen = UINT32_MAX0xffffffffU;
2966 continue;
2967 } else if (j >= oid->aoi_idlen || overflow == -1) {
2968 data->avb_oid.aoi_idlen = 0;
2969 continue;
2970 }
2971 if (agentx_object_implied(axo, index->axv_axi))
2972 data->avb_oid.aoi_idlen = oid->aoi_idlen - j;
2973 else {
2974 data->avb_oid.aoi_idlen = oid->aoi_id[j++];
2975 if (data->avb_oid.aoi_idlen >=
2976 AGENTX_OID_MAX_LEN128 - j) {
2977 data->avb_oid.aoi_idlen = UINT32_MAX0xffffffffU;
2978 overflow = 1;
2979 }
2980 }
2981 if (data->avb_oid.aoi_idlen == UINT32_MAX0xffffffffU ||
2982 data->avb_oid.aoi_idlen == 0)
2983 continue;
2984 for (k = 0; k < data->avb_oid.aoi_idlen; k++, j++) {
2985 if (overflow == 1)
2986 data->avb_oid.aoi_id[k] = UINT32_MAX0xffffffffU;
2987 else if (j >= oid->aoi_idlen || overflow == -1)
2988 data->avb_oid.aoi_id[k] = 0;
2989 else
2990 data->avb_oid.aoi_id[k] =
2991 oid->aoi_id[j];
2992 }
2993 j--;
2994 break;
2995 case AX_DATA_TYPE_IPADDRESS:
2996 ipaddress = malloc(sizeof(*ipaddress));
2997 if (ipaddress == NULL((void *)0)) {
2998 agentx_log_axg_warn(axg,
2999 "Failed to bind ipaddress index");
3000 agentx_varbind_error_type(axv,
3001 AX_PDU_ERROR_PROCESSINGERROR, 1);
3002 return;
3003 }
3004 ipbytes = (unsigned char *)ipaddress;
3005 for (k = 0; k < 4; k++, j++) {
3006 if (j < oid->aoi_idlen && oid->aoi_id[j] > 255)
3007 overflow = 1;
3008 if (overflow == 1)
3009 ipbytes[k] = 255;
3010 else if (j >= oid->aoi_idlen || overflow == -1)
3011 ipbytes[k] = 0;
3012 else
3013 ipbytes[k] = oid->aoi_id[j];
3014 }
3015 j--;
3016 data->avb_ostring.aos_slen = sizeof(*ipaddress);
3017 data->avb_ostring.aos_string =
3018 (unsigned char *)ipaddress;
3019 break;
3020 default:
3021#ifdef AX_DEBUG
3022 agentx_log_axg_fatalx(axg,
3023 "%s: unexpected index type", __func__);
3024#else
3025 agentx_log_axg_warnx(axg,
3026 "%s: unexpected index type", __func__);
3027 agentx_varbind_error_type(axv,
3028 AX_PDU_ERROR_PROCESSINGERROR, 1);
3029 return;
3030#endif
3031 }
3032 }
3033 if (axv->axv_axg->axg_type == AX_PDU_TYPE_GET) {
3034 if (j != oid->aoi_idlen || overflow) {
3035 agentx_varbind_nosuchinstance(axv);
3036 return;
3037 }
3038 }
3039
3040 if (overflow == 1) {
3041 axv->axv_include = 0;
3042 } else if (overflow == -1) {
3043 axv->axv_include = 1;
3044 } else if (j < oid->aoi_idlen)
3045 axv->axv_include = 0;
3046 else if (j > oid->aoi_idlen)
3047 axv->axv_include = 1;
3048 if (agentx_varbind_request(axv) == AGENTX_REQUEST_TYPE_GETNEXT &&
3049 !dynamic) {
3050 agentx_varbind_endofmibview(axv);
3051 return;
3052 }
3053
3054 axo->axo_get(axv);
3055}
3056
3057void
3058agentx_varbind_integer(struct agentx_varbind *axv, int32_t value)
3059{
3060 axv->axv_vb.avb_type = AX_DATA_TYPE_INTEGER;
3061 axv->axv_vb.avb_data.avb_int32 = value;
3062
3063 agentx_varbind_finalize(axv);
3064}
3065
3066void
3067agentx_varbind_string(struct agentx_varbind *axv, const char *value)
3068{
3069 agentx_varbind_nstring(axv, (const unsigned char *)value,
3070 strlen(value));
3071}
3072
3073void
3074agentx_varbind_nstring(struct agentx_varbind *axv,
3075 const unsigned char *value, size_t slen)
3076{
3077 axv->axv_vb.avb_data.avb_ostring.aos_string = malloc(slen);
3078 if (axv->axv_vb.avb_data.avb_ostring.aos_string == NULL((void *)0)) {
3079 agentx_log_axg_warn(axv->axv_axg, "Couldn't bind string");
3080 agentx_varbind_error_type(axv,
3081 AX_PDU_ERROR_PROCESSINGERROR, 1);
3082 return;
3083 }
3084 axv->axv_vb.avb_type = AX_DATA_TYPE_OCTETSTRING;
3085 memcpy(axv->axv_vb.avb_data.avb_ostring.aos_string, value, slen);
3086 axv->axv_vb.avb_data.avb_ostring.aos_slen = slen;
3087
3088 agentx_varbind_finalize(axv);
3089}
3090
3091void
3092agentx_varbind_printf(struct agentx_varbind *axv, const char *fmt, ...)
3093{
3094 va_list ap;
3095 int r;
3096
3097 axv->axv_vb.avb_type = AX_DATA_TYPE_OCTETSTRING;
3098 va_start(ap, fmt)__builtin_va_start((ap), fmt);
3099 r = vasprintf((char **)&(axv->axv_vb.avb_data.avb_ostring.aos_string),
3100 fmt, ap);
3101 va_end(ap)__builtin_va_end((ap));
3102 if (r == -1) {
3103 axv->axv_vb.avb_data.avb_ostring.aos_string = NULL((void *)0);
3104 agentx_log_axg_warn(axv->axv_axg, "Couldn't bind string");
3105 agentx_varbind_error_type(axv, AX_PDU_ERROR_PROCESSINGERROR, 1);
3106 return;
3107 }
3108 axv->axv_vb.avb_data.avb_ostring.aos_slen = r;
3109
3110 agentx_varbind_finalize(axv);
3111}
3112
3113void
3114agentx_varbind_null(struct agentx_varbind *axv)
3115{
3116 axv->axv_vb.avb_type = AX_DATA_TYPE_NULL;
3117
3118 agentx_varbind_finalize(axv);
3119}
3120
3121void
3122agentx_varbind_oid(struct agentx_varbind *axv, const uint32_t oid[],
3123 size_t oidlen)
3124{
3125 const char *errstr;
3126
3127 axv->axv_vb.avb_type = AX_DATA_TYPE_OID;
3128
3129 if (agentx_oidfill(&(axv->axv_vb.avb_data.avb_oid),
3130 oid, oidlen, &errstr) == -1) {
3131#ifdef AX_DEBUG
3132 agentx_log_axg_fatalx(axv->axv_axg, "%s: %s", __func__, errstr);
3133#else
3134 agentx_log_axg_warnx(axv->axv_axg, "%s: %s", __func__, errstr);
3135 agentx_varbind_error_type(axv, AX_PDU_ERROR_PROCESSINGERROR, 1);
3136 return;
3137#endif
3138 }
3139
3140 agentx_varbind_finalize(axv);
3141}
3142
3143void
3144agentx_varbind_object(struct agentx_varbind *axv,
3145 struct agentx_object *axo)
3146{
3147 agentx_varbind_oid(axv, axo->axo_oid.aoi_id,
3148 axo->axo_oid.aoi_idlen);
3149}
3150
3151void
3152agentx_varbind_index(struct agentx_varbind *axv,
3153 struct agentx_index *axi)
3154{
3155 agentx_varbind_oid(axv, axi->axi_vb.avb_oid.aoi_id,
3156 axi->axi_vb.avb_oid.aoi_idlen);
3157}
3158
3159
3160void
3161agentx_varbind_ipaddress(struct agentx_varbind *axv,
3162 const struct in_addr *value)
3163{
3164 axv->axv_vb.avb_type = AX_DATA_TYPE_IPADDRESS;
3165 axv->axv_vb.avb_data.avb_ostring.aos_string = malloc(4);
3166 if (axv->axv_vb.avb_data.avb_ostring.aos_string == NULL((void *)0)) {
3167 agentx_log_axg_warn(axv->axv_axg, "Couldn't bind ipaddress");
3168 agentx_varbind_error_type(axv,
3169 AX_PDU_ERROR_PROCESSINGERROR, 1);
3170 return;
3171 }
3172 memcpy(axv->axv_vb.avb_data.avb_ostring.aos_string, value, 4);
3173 axv->axv_vb.avb_data.avb_ostring.aos_slen = 4;
3174
3175 agentx_varbind_finalize(axv);
3176}
3177
3178void
3179agentx_varbind_counter32(struct agentx_varbind *axv, uint32_t value)
3180{
3181 axv->axv_vb.avb_type = AX_DATA_TYPE_COUNTER32;
3182 axv->axv_vb.avb_data.avb_uint32 = value;
3183
3184 agentx_varbind_finalize(axv);
3185}
3186
3187void
3188agentx_varbind_gauge32(struct agentx_varbind *axv, uint32_t value)
3189{
3190 axv->axv_vb.avb_type = AX_DATA_TYPE_GAUGE32;
3191 axv->axv_vb.avb_data.avb_uint32 = value;
3192
3193 agentx_varbind_finalize(axv);
3194}
3195
3196void
3197agentx_varbind_unsigned32(struct agentx_varbind *axv, uint32_t value)
3198{
3199 agentx_varbind_gauge32(axv, value);
3200}
3201
3202void
3203agentx_varbind_timeticks(struct agentx_varbind *axv, uint32_t value)
3204{
3205 axv->axv_vb.avb_type = AX_DATA_TYPE_TIMETICKS;
3206 axv->axv_vb.avb_data.avb_uint32 = value;
3207
3208 agentx_varbind_finalize(axv);
3209}
3210
3211void
3212agentx_varbind_opaque(struct agentx_varbind *axv, const char *string,
3213 size_t strlen)
3214{
3215 axv->axv_vb.avb_type = AX_DATA_TYPE_OPAQUE;
3216 axv->axv_vb.avb_data.avb_ostring.aos_string = malloc(strlen);
3217 if (axv->axv_vb.avb_data.avb_ostring.aos_string == NULL((void *)0)) {
3218 agentx_log_axg_warn(axv->axv_axg, "Couldn't bind opaque");
3219 agentx_varbind_error_type(axv,
3220 AX_PDU_ERROR_PROCESSINGERROR, 1);
3221 return;
3222 }
3223 memcpy(axv->axv_vb.avb_data.avb_ostring.aos_string, string, strlen);
3224 axv->axv_vb.avb_data.avb_ostring.aos_slen = strlen;
3225
3226 agentx_varbind_finalize(axv);
3227}
3228
3229void
3230agentx_varbind_counter64(struct agentx_varbind *axv, uint64_t value)
3231{
3232 axv->axv_vb.avb_type = AX_DATA_TYPE_COUNTER64;
3233 axv->axv_vb.avb_data.avb_uint64 = value;
3234
3235 agentx_varbind_finalize(axv);
3236}
3237
3238void
3239agentx_varbind_notfound(struct agentx_varbind *axv)
3240{
3241 if (axv->axv_indexlen == 0) {
3242#ifdef AX_DEBUG
3243 agentx_log_axg_fatalx(axv->axv_axg, "%s invalid call",
3244 __func__);
3245#else
3246 agentx_log_axg_warnx(axv->axv_axg, "%s invalid call",
3247 __func__);
3248 agentx_varbind_error_type(axv,
3249 AX_PDU_ERROR_GENERR, 1);
3250#endif
3251 } else if (axv->axv_axg->axg_type == AX_PDU_TYPE_GET)
3252 agentx_varbind_nosuchinstance(axv);
3253 else
3254 agentx_varbind_endofmibview(axv);
3255}
3256
3257void
3258agentx_varbind_error(struct agentx_varbind *axv)
3259{
3260 agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 1);
3261}
3262
3263static void
3264agentx_varbind_error_type(struct agentx_varbind *axv,
3265 enum ax_pdu_error error, int done)
3266{
3267 if (axv->axv_error == AX_PDU_ERROR_NOERROR) {
3268 axv->axv_error = error;
3269 }
3270
3271 if (done) {
3272 axv->axv_vb.avb_type = AX_DATA_TYPE_NULL;
3273
3274 agentx_varbind_finalize(axv);
3275 }
3276}
3277
3278static void
3279agentx_varbind_finalize(struct agentx_varbind *axv)
3280{
3281 struct agentx_get *axg = axv->axv_axg;
3282 struct ax_oid oid;
3283 union ax_data *data;
3284 size_t i, j;
3285 int cmp;
3286
3287 if (axv->axv_error != AX_PDU_ERROR_NOERROR) {
3288 bcopy(&(axv->axv_start), &(axv->axv_vb.avb_oid),
3289 sizeof(axv->axv_start));
3290 goto done;
3291 }
3292 bcopy(&(axv->axv_axo->axo_oid), &oid, sizeof(oid));
3293 if (axv->axv_indexlen == 0)
3294 ax_oid_add(&oid, 0);
3295 for (i = 0; i < axv->axv_indexlen; i++) {
3296 data = &(axv->axv_index[i].axv_idata);
3297 switch (axv->axv_index[i].axv_axi->axi_vb.avb_type) {
3298 case AX_DATA_TYPE_INTEGER:
3299 if (ax_oid_add(&oid, data->avb_int32) == -1)
3300 goto fail;
3301 break;
3302 case AX_DATA_TYPE_OCTETSTRING:
3303 if (!agentx_object_implied(axv->axv_axo,
3304 axv->axv_index[i].axv_axi)) {
3305 if (ax_oid_add(&oid,
3306 data->avb_ostring.aos_slen) == -1)
3307 goto fail;
3308 }
3309 for (j = 0; j < data->avb_ostring.aos_slen; j++) {
3310 if (ax_oid_add(&oid,
3311 (uint8_t)data->avb_ostring.aos_string[j]) ==
3312 -1)
3313 goto fail;
3314 }
3315 break;
3316 case AX_DATA_TYPE_OID:
3317 if (!agentx_object_implied(axv->axv_axo,
3318 axv->axv_index[i].axv_axi)) {
3319 if (ax_oid_add(&oid,
3320 data->avb_oid.aoi_idlen) == -1)
3321 goto fail;
3322 }
3323 for (j = 0; j < data->avb_oid.aoi_idlen; j++) {
3324 if (ax_oid_add(&oid,
3325 data->avb_oid.aoi_id[j]) == -1)
3326 goto fail;
3327 }
3328 break;
3329 case AX_DATA_TYPE_IPADDRESS:
3330 for (j = 0; j < 4; j++) {
3331 if (ax_oid_add(&oid,
3332 data->avb_ostring.aos_string == NULL((void *)0) ? 0 :
3333 (uint8_t)data->avb_ostring.aos_string[j]) ==
3334 -1)
3335 goto fail;
3336 }
3337 break;
3338 default:
3339#ifdef AX_DEBUG
3340 agentx_log_axg_fatalx(axg,
3341 "%s: unsupported index type", __func__);
3342#else
3343 bcopy(&(axv->axv_start), &(axv->axv_vb.avb_oid),
3344 sizeof(axv->axv_start));
3345 axv->axv_error = AX_PDU_ERROR_PROCESSINGERROR;
3346 agentx_object_unlock(axv->axv_axo);
3347 agentx_get_finalize(axv->axv_axg);
3348 return;
3349#endif
3350 }
3351 }
3352 cmp = ax_oid_cmp(&oid, &(axv->axv_vb.avb_oid));
3353 switch (agentx_varbind_request(axv)) {
3354 case AGENTX_REQUEST_TYPE_GET:
3355 if (cmp != 0) {
3356#ifdef AX_DEBUG
3357 agentx_log_axg_fatalx(axg, "index changed");
3358#else
3359 agentx_log_axg_warnx(axg, "index changed");
3360 bcopy(&(axv->axv_start), &(axv->axv_vb.avb_oid),
3361 sizeof(axv->axv_start));
3362 axv->axv_error = AX_PDU_ERROR_GENERR;
3363 break;
3364#endif
3365 }
3366 break;
3367 case AGENTX_REQUEST_TYPE_GETNEXT:
3368 if (cmp <= 0) {
3369#ifdef AX_DEBUG
3370 agentx_log_axg_fatalx(axg, "indices not incremented");
3371#else
3372 agentx_log_axg_warnx(axg, "indices not incremented");
3373 bcopy(&(axv->axv_start), &(axv->axv_vb.avb_oid),
3374 sizeof(axv->axv_start));
3375 axv->axv_error = AX_PDU_ERROR_GENERR;
3376 break;
3377#endif
3378 }
3379 /* FALLTHROUGH */
3380 case AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE:
3381 if (cmp < 0) {
3382#ifdef AX_DEBUG
3383 agentx_log_axg_fatalx(axg, "index decremented");
3384#else
3385 agentx_log_axg_warnx(axg, "index decremented");
3386 bcopy(&(axv->axv_start), &(axv->axv_vb.avb_oid),
3387 sizeof(axv->axv_start));
3388 axv->axv_error = AX_PDU_ERROR_GENERR;
3389 break;
3390#endif
3391 }
3392 if (axv->axv_end.aoi_idlen != 0 &&
3393 ax_oid_cmp(&oid, &(axv->axv_end)) >= 0) {
3394 agentx_varbind_endofmibview(axv);
3395 return;
3396 }
3397 bcopy(&oid, &(axv->axv_vb.avb_oid), sizeof(oid));
3398 }
3399done:
3400 agentx_object_unlock(axv->axv_axo);
3401 agentx_get_finalize(axv->axv_axg);
3402 return;
3403
3404fail:
3405 agentx_log_axg_warnx(axg, "oid too large");
3406 bcopy(&(axv->axv_start), &(axv->axv_vb.avb_oid),
3407 sizeof(axv->axv_start));
3408 axv->axv_error = AX_PDU_ERROR_GENERR;
3409 agentx_object_unlock(axv->axv_axo);
3410 agentx_get_finalize(axv->axv_axg);
3411}
3412
3413static void
3414agentx_varbind_nosuchobject(struct agentx_varbind *axv)
3415{
3416 axv->axv_vb.avb_type = AX_DATA_TYPE_NOSUCHOBJECT;
3417
3418 if (axv->axv_axo != NULL((void *)0))
3419 agentx_object_unlock(axv->axv_axo);
3420 agentx_get_finalize(axv->axv_axg);
3421}
3422
3423static void
3424agentx_varbind_nosuchinstance(struct agentx_varbind *axv)
3425{
3426 axv->axv_vb.avb_type = AX_DATA_TYPE_NOSUCHINSTANCE;
3427
3428 if (axv->axv_axo != NULL((void *)0))
3429 agentx_object_unlock(axv->axv_axo);
3430 agentx_get_finalize(axv->axv_axg);
3431}
3432
3433static void
3434agentx_varbind_endofmibview(struct agentx_varbind *axv)
3435{
3436 struct agentx_object *axo;
3437 struct ax_varbind *vb;
3438 struct agentx_varbind_index *index;
3439 size_t i;
3440
3441#ifdef AX_DEBUG
3442 if (axv->axv_axg->axg_type != AX_PDU_TYPE_GETNEXT &&
3443 axv->axv_axg->axg_type != AX_PDU_TYPE_GETBULK)
3444 agentx_log_axg_fatalx(axv->axv_axg,
3445 "%s: invalid request type", __func__);
3446#endif
3447
3448 if (axv->axv_axo != NULL((void *)0) &&
3449 (axo = RB_NEXT(axc_objects, &(axc->axc_objects),axc_objects_RB_NEXT(axv->axv_axo)
3450 axv->axv_axo)axc_objects_RB_NEXT(axv->axv_axo)) != NULL((void *)0) &&
3451 ax_oid_cmp(&(axo->axo_oid), &(axv->axv_end)) < 0) {
3452 bcopy(&(axo->axo_oid), &(axv->axv_vb.avb_oid),
3453 sizeof(axo->axo_oid));
3454 axv->axv_include = 1;
3455 for (i = 0; i < axv->axv_indexlen; i++) {
3456 index = &(axv->axv_index[i]);
3457 vb = &(index->axv_axi->axi_vb);
3458 if (vb->avb_type == AX_DATA_TYPE_OCTETSTRING ||
3459 vb->avb_type == AX_DATA_TYPE_IPADDRESS)
3460 free(index->axv_idata.avb_ostring.aos_string);
3461 }
3462 bzero(&(axv->axv_index), sizeof(axv->axv_index));
3463 agentx_object_unlock(axv->axv_axo);
3464 agentx_varbind_start(axv);
3465 return;
3466 }
3467
3468 bcopy(&(axv->axv_start), &(axv->axv_vb.avb_oid),
3469 sizeof(axv->axv_start));
3470 axv->axv_vb.avb_type = AX_DATA_TYPE_ENDOFMIBVIEW;
3471
3472 if (axv->axv_axo != NULL((void *)0))
3473 agentx_object_unlock(axv->axv_axo);
3474 agentx_get_finalize(axv->axv_axg);
3475}
3476
3477enum agentx_request_type
3478agentx_varbind_request(struct agentx_varbind *axv)
3479{
3480 if (axv->axv_axg->axg_type == AX_PDU_TYPE_GET)
3481 return AGENTX_REQUEST_TYPE_GET;
3482 if (axv->axv_include)
3483 return AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE;
3484 return AGENTX_REQUEST_TYPE_GETNEXT;
3485}
3486
3487struct agentx_object *
3488agentx_varbind_get_object(struct agentx_varbind *axv)
3489{
3490 return axv->axv_axo;
3491}
3492
3493int32_t
3494agentx_varbind_get_index_integer(struct agentx_varbind *axv,
3495 struct agentx_index *axi)
3496{
3497 size_t i;
3498
3499 if (axi->axi_vb.avb_type != AX_DATA_TYPE_INTEGER) {
3500#ifdef AX_DEBUG
3501 agentx_log_axg_fatalx(axv->axv_axg, "invalid index type");
3502#else
3503 agentx_log_axg_warnx(axv->axv_axg, "invalid index type");
3504 agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
3505 return 0;
3506#endif
3507 }
3508
3509 for (i = 0; i < axv->axv_indexlen; i++) {
3510 if (axv->axv_index[i].axv_axi == axi)
3511 return axv->axv_index[i].axv_idata.avb_int32;
3512 }
3513#ifdef AX_DEBUG
3514 agentx_log_axg_fatalx(axv->axv_axg, "invalid index");
3515#else
3516 agentx_log_axg_warnx(axv->axv_axg, "invalid index");
3517 agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
3518 return 0;
3519#endif
3520}
3521
3522const unsigned char *
3523agentx_varbind_get_index_string(struct agentx_varbind *axv,
3524 struct agentx_index *axi, size_t *slen, int *implied)
3525{
3526 struct agentx_varbind_index *index;
3527 size_t i;
3528
3529 if (axi->axi_vb.avb_type != AX_DATA_TYPE_OCTETSTRING) {
3530#ifdef AX_DEBUG
3531 agentx_log_axg_fatalx(axv->axv_axg, "invalid index type");
3532#else
3533 agentx_log_axg_warnx(axv->axv_axg, "invalid index type");
3534 agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
3535 *slen = 0;
3536 *implied = 0;
3537 return NULL((void *)0);
3538#endif
3539 }
3540
3541 for (i = 0; i < axv->axv_indexlen; i++) {
3542 if (axv->axv_index[i].axv_axi == axi) {
3543 index = &(axv->axv_index[i]);
3544 *slen = index->axv_idata.avb_ostring.aos_slen;
3545 *implied = agentx_object_implied(axv->axv_axo, axi);
3546 return index->axv_idata.avb_ostring.aos_string;
3547 }
3548 }
3549
3550#ifdef AX_DEBUG
3551 agentx_log_axg_fatalx(axv->axv_axg, "invalid index");
3552#else
3553 agentx_log_axg_warnx(axv->axv_axg, "invalid index");
3554 agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
3555 *slen = 0;
3556 *implied = 0;
3557 return NULL((void *)0);
3558#endif
3559}
3560
3561const uint32_t *
3562agentx_varbind_get_index_oid(struct agentx_varbind *axv,
3563 struct agentx_index *axi, size_t *oidlen, int *implied)
3564{
3565 struct agentx_varbind_index *index;
3566 size_t i;
3567
3568 if (axi->axi_vb.avb_type != AX_DATA_TYPE_OID) {
3569#ifdef AX_DEBUG
3570 agentx_log_axg_fatalx(axv->axv_axg, "invalid index type");
3571#else
3572 agentx_log_axg_warnx(axv->axv_axg, "invalid index type");
3573 agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
3574 *oidlen = 0;
3575 *implied = 0;
3576 return NULL((void *)0);
3577#endif
3578 }
3579
3580 for (i = 0; i < axv->axv_indexlen; i++) {
3581 if (axv->axv_index[i].axv_axi == axi) {
3582 index = &(axv->axv_index[i]);
3583 *oidlen = index->axv_idata.avb_oid.aoi_idlen;
3584 *implied = agentx_object_implied(axv->axv_axo, axi);
3585 return index->axv_idata.avb_oid.aoi_id;
3586 }
3587 }
3588
3589#ifdef AX_DEBUG
3590 agentx_log_axg_fatalx(axv->axv_axg, "invalid index");
3591#else
3592 agentx_log_axg_warnx(axv->axv_axg, "invalid index");
3593 agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
3594 *oidlen = 0;
3595 *implied = 0;
3596 return NULL((void *)0);
3597#endif
3598}
3599
3600const struct in_addr *
3601agentx_varbind_get_index_ipaddress(struct agentx_varbind *axv,
3602 struct agentx_index *axi)
3603{
3604 static struct in_addr nuladdr = {0};
3605 struct agentx_varbind_index *index;
3606 size_t i;
3607
3608 if (axi->axi_vb.avb_type != AX_DATA_TYPE_IPADDRESS) {
3609#ifdef AX_DEBUG
3610 agentx_log_axg_fatalx(axv->axv_axg, "invalid index type");
3611#else
3612 agentx_log_axg_warnx(axv->axv_axg, "invalid index type");
3613 agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
3614 return NULL((void *)0);
3615#endif
3616 }
3617
3618 for (i = 0; i < axv->axv_indexlen; i++) {
3619 if (axv->axv_index[i].axv_axi == axi) {
3620 index = &(axv->axv_index[i]);
3621 if (index->axv_idata.avb_ostring.aos_string == NULL((void *)0))
3622 return &nuladdr;
3623 return (struct in_addr *)
3624 index->axv_idata.avb_ostring.aos_string;
3625 }
3626 }
3627
3628#ifdef AX_DEBUG
3629 agentx_log_axg_fatalx(axv->axv_axg, "invalid index");
3630#else
3631 agentx_log_axg_warnx(axv->axv_axg, "invalid index");
3632 agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
3633 return NULL((void *)0);
3634#endif
3635}
3636
3637void
3638agentx_varbind_set_index_integer(struct agentx_varbind *axv,
3639 struct agentx_index *axi, int32_t value)
3640{
3641 size_t i;
3642
3643 if (axi->axi_vb.avb_type != AX_DATA_TYPE_INTEGER) {
3644#ifdef AX_DEBUG
3645 agentx_log_axg_fatalx(axv->axv_axg, "invalid index type");
3646#else
3647 agentx_log_axg_warnx(axv->axv_axg, "invalid index type");
3648 agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
3649 return;
3650#endif
3651 }
3652
3653 if (value < 0) {
3654#ifdef AX_DEBUG
3655 agentx_log_axg_fatalx(axv->axv_axg, "invalid index value");
3656#else
3657 agentx_log_axg_warnx(axv->axv_axg, "invalid index value");
3658 agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
3659 return;
3660#endif
3661 }
3662
3663 for (i = 0; i < axv->axv_indexlen; i++) {
3664 if (axv->axv_index[i].axv_axi == axi) {
3665 if (axv->axv_axg->axg_type == AX_PDU_TYPE_GET &&
3666 axv->axv_index[i].axv_idata.avb_int32 != value) {
3667#ifdef AX_DEBUG
3668 agentx_log_axg_fatalx(axv->axv_axg,
3669 "can't change index on GET");
3670#else
3671 agentx_log_axg_warnx(axv->axv_axg,
3672 "can't change index on GET");
3673 agentx_varbind_error_type(axv,
3674 AX_PDU_ERROR_GENERR, 0);
3675 return;
3676#endif
3677 }
3678 axv->axv_index[i].axv_idata.avb_int32 = value;
3679 return;
3680 }
3681 }
3682#ifdef AX_DEBUG
3683 agentx_log_axg_fatalx(axv->axv_axg, "invalid index");
3684#else
3685 agentx_log_axg_warnx(axv->axv_axg, "invalid index");
3686 agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
3687#endif
3688}
3689
3690void
3691agentx_varbind_set_index_string(struct agentx_varbind *axv,
3692 struct agentx_index *axi, const char *value)
3693{
3694 agentx_varbind_set_index_nstring(axv, axi,
3695 (const unsigned char *)value, strlen(value));
3696}
3697
3698void
3699agentx_varbind_set_index_nstring(struct agentx_varbind *axv,
3700 struct agentx_index *axi, const unsigned char *value, size_t slen)
3701{
3702 struct ax_ostring *curvalue;
3703 unsigned char *nstring;
3704 size_t i;
3705
3706 if (axi->axi_vb.avb_type != AX_DATA_TYPE_OCTETSTRING) {
3707#ifdef AX_DEBUG
3708 agentx_log_axg_fatalx(axv->axv_axg, "invalid index type");
3709#else
3710 agentx_log_axg_warnx(axv->axv_axg, "invalid index type");
3711 agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
3712 return;
3713#endif
3714 }
3715
3716 for (i = 0; i < axv->axv_indexlen; i++) {
3717 if (axv->axv_index[i].axv_axi == axi) {
3718 if (axi->axi_vb.avb_data.avb_ostring.aos_slen != 0 &&
3719 axi->axi_vb.avb_data.avb_ostring.aos_slen != slen) {
3720#ifdef AX_DEBUG
3721 agentx_log_axg_fatalx(axv->axv_axg,
3722 "invalid string length on explicit length "
3723 "string");
3724#else
3725 agentx_log_axg_warnx(axv->axv_axg,
3726 "invalid string length on explicit length "
3727 "string");
3728 agentx_varbind_error_type(axv,
3729 AX_PDU_ERROR_GENERR, 0);
3730 return;
3731#endif
3732 }
3733 curvalue = &(axv->axv_index[i].axv_idata.avb_ostring);
3734 if (axv->axv_axg->axg_type == AX_PDU_TYPE_GET &&
3735 (curvalue->aos_slen != slen ||
3736 memcmp(curvalue->aos_string, value, slen) != 0)) {
3737#ifdef AX_DEBUG
3738 agentx_log_axg_fatalx(axv->axv_axg,
3739 "can't change index on GET");
3740#else
3741 agentx_log_axg_warnx(axv->axv_axg,
3742 "can't change index on GET");
3743 agentx_varbind_error_type(axv,
3744 AX_PDU_ERROR_GENERR, 0);
3745 return;
3746#endif
3747 }
3748 if ((nstring = recallocarray(curvalue->aos_string,
3749 curvalue->aos_slen + 1, slen + 1, 1)) == NULL((void *)0)) {
3750 agentx_log_axg_warn(axv->axv_axg,
3751 "Failed to bind string index");
3752 agentx_varbind_error_type(axv,
3753 AX_PDU_ERROR_PROCESSINGERROR, 0);
3754 return;
3755 }
3756 curvalue->aos_string = nstring;
3757 memcpy(nstring, value, slen);
3758 curvalue->aos_slen = slen;
3759 return;
3760 }
3761 }
3762#ifdef AX_DEBUG
3763 agentx_log_axg_fatalx(axv->axv_axg, "invalid index");
3764#else
3765 agentx_log_axg_warnx(axv->axv_axg, "invalid index");
3766 agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
3767#endif
3768}
3769
3770void
3771agentx_varbind_set_index_oid(struct agentx_varbind *axv,
3772 struct agentx_index *axi, const uint32_t *value, size_t oidlen)
3773{
3774 struct ax_oid *curvalue, oid;
3775 const char *errstr;
3776 size_t i;
3777
3778 if (axi->axi_vb.avb_type != AX_DATA_TYPE_OID) {
3779#ifdef AX_DEBUG
3780 agentx_log_axg_fatalx(axv->axv_axg, "invalid index type");
3781#else
3782 agentx_log_axg_warnx(axv->axv_axg, "invalid index type");
3783 agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
3784 return;
3785#endif
3786 }
3787
3788 for (i = 0; i < axv->axv_indexlen; i++) {
3789 if (axv->axv_index[i].axv_axi == axi) {
3790 if (axi->axi_vb.avb_data.avb_oid.aoi_idlen != 0 &&
3791 axi->axi_vb.avb_data.avb_oid.aoi_idlen != oidlen) {
3792#ifdef AX_DEBUG
3793 agentx_log_axg_fatalx(axv->axv_axg,
3794 "invalid oid length on explicit length "
3795 "oid");
3796#else
3797 agentx_log_axg_warnx(axv->axv_axg,
3798 "invalid oid length on explicit length "
3799 "oid");
3800 agentx_varbind_error_type(axv,
3801 AX_PDU_ERROR_GENERR, 0);
3802 return;
3803#endif
3804 }
3805 curvalue = &(axv->axv_index[i].axv_idata.avb_oid);
3806 if (agentx_oidfill(&oid, value,
3807 oidlen, &errstr) == -1) {
3808#ifdef AX_DEBUG
3809 agentx_log_axg_fatalx(axv->axv_axg, "%s: %s",
3810 __func__, errstr);
3811#else
3812 agentx_log_axg_warnx(axv->axv_axg, "%s: %s",
3813 __func__, errstr);
3814 agentx_varbind_error_type(axv,
3815 AX_PDU_ERROR_PROCESSINGERROR, 1);
3816 return;
3817#endif
3818 }
3819
3820 if (axv->axv_axg->axg_type == AX_PDU_TYPE_GET &&
3821 ax_oid_cmp(&oid, curvalue) != 0) {
3822#ifdef AX_DEBUG
3823 agentx_log_axg_fatalx(axv->axv_axg,
3824 "can't change index on GET");
3825#else
3826 agentx_log_axg_warnx(axv->axv_axg,
3827 "can't change index on GET");
3828 agentx_varbind_error_type(axv,
3829 AX_PDU_ERROR_GENERR, 0);
3830 return;
3831#endif
3832 }
3833
3834 *curvalue = oid;
3835 return;
3836 }
3837 }
3838#ifdef AX_DEBUG
3839 agentx_log_axg_fatalx(axv->axv_axg, "invalid index");
3840#else
3841 agentx_log_axg_warnx(axv->axv_axg, "invalid index");
3842 agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
3843#endif
3844}
3845
3846void
3847agentx_varbind_set_index_object(struct agentx_varbind *axv,
3848 struct agentx_index *axi, struct agentx_object *axo)
3849{
3850 agentx_varbind_set_index_oid(axv, axi, axo->axo_oid.aoi_id,
3851 axo->axo_oid.aoi_idlen);
3852}
3853
3854void
3855agentx_varbind_set_index_ipaddress(struct agentx_varbind *axv,
3856 struct agentx_index *axi, const struct in_addr *addr)
3857{
3858 struct ax_ostring *curvalue;
3859 size_t i;
3860
3861 if (axi->axi_vb.avb_type != AX_DATA_TYPE_IPADDRESS) {
3862#ifdef AX_DEBUG
3863 agentx_log_axg_fatalx(axv->axv_axg, "invalid index type");
3864#else
3865 agentx_log_axg_warnx(axv->axv_axg, "invalid index type");
3866 agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
3867 return;
3868#endif
3869 }
3870
3871 for (i = 0; i < axv->axv_indexlen; i++) {
3872 if (axv->axv_index[i].axv_axi == axi) {
3873 curvalue = &(axv->axv_index[i].axv_idata.avb_ostring);
3874 if (curvalue->aos_string == NULL((void *)0))
3875 curvalue->aos_string = calloc(1, sizeof(*addr));
Result of 'calloc' is converted to a pointer of type 'unsigned char', which is incompatible with sizeof operand type 'const struct in_addr'
3876 if (curvalue->aos_string == NULL((void *)0)) {
3877 agentx_log_axg_warn(axv->axv_axg,
3878 "Failed to bind ipaddress index");
3879 agentx_varbind_error_type(axv,
3880 AX_PDU_ERROR_PROCESSINGERROR, 0);
3881 return;
3882 }
3883 if (axv->axv_axg->axg_type == AX_PDU_TYPE_GET &&
3884 memcmp(addr, curvalue->aos_string,
3885 sizeof(*addr)) != 0) {
3886#ifdef AX_DEBUG
3887 agentx_log_axg_fatalx(axv->axv_axg,
3888 "can't change index on GET");
3889#else
3890 agentx_log_axg_warnx(axv->axv_axg,
3891 "can't change index on GET");
3892 agentx_varbind_error_type(axv,
3893 AX_PDU_ERROR_GENERR, 0);
3894 return;
3895#endif
3896 }
3897 bcopy(addr, curvalue->aos_string, sizeof(*addr));
3898 return;
3899 }
3900 }
3901#ifdef AX_DEBUG
3902 agentx_log_axg_fatalx(axv->axv_axg, "invalid index");
3903#else
3904 agentx_log_axg_warnx(axv->axv_axg, "invalid index");
3905 agentx_varbind_error_type(axv, AX_PDU_ERROR_GENERR, 0);
3906#endif
3907}
3908
3909static int
3910agentx_request(struct agentx *ax, uint32_t packetid,
3911 int (*cb)(struct ax_pdu *, void *), void *cookie)
3912{
3913 struct agentx_request *axr;
3914
3915#ifdef AX_DEBUG
3916 if (ax->ax_ax->ax_wblen == 0)
3917 agentx_log_ax_fatalx(ax, "%s: no data to be written",
3918 __func__);
3919#endif
3920
3921 if ((axr = calloc(1, sizeof(*axr))) == NULL((void *)0)) {
3922 agentx_log_ax_warn(ax, "couldn't create request context");
3923 agentx_reset(ax);
3924 return -1;
3925 }
3926
3927 axr->axr_packetid = packetid;
3928 axr->axr_cb = cb;
3929 axr->axr_cookie = cookie;
3930 if (RB_INSERT(ax_requests, &(ax->ax_requests), axr)ax_requests_RB_INSERT(&(ax->ax_requests), axr) != NULL((void *)0)) {
3931#ifdef AX_DEBUG
3932 agentx_log_ax_fatalx(ax, "%s: duplicate packetid", __func__);
3933#else
3934 agentx_log_ax_warnx(ax, "%s: duplicate packetid", __func__);
3935 free(axr);
3936 agentx_reset(ax);
3937 return -1;
3938#endif
3939 }
3940
3941 agentx_wantwrite(ax, ax->ax_fd);
3942 return 0;
3943}
3944
3945static int
3946agentx_request_cmp(struct agentx_request *r1,
3947 struct agentx_request *r2)
3948{
3949 return r1->axr_packetid < r2->axr_packetid ? -1 :
3950 r1->axr_packetid > r2->axr_packetid;
3951}
3952
3953static int
3954agentx_strcat(char **dst, const char *src)
3955{
3956 char *tmp;
3957 size_t dstlen = 0, buflen = 0, srclen, nbuflen;
3958
3959 if (*dst != NULL((void *)0)) {
3960 dstlen = strlen(*dst);
3961 buflen = ((dstlen / 512) + 1) * 512;
3962 }
3963
3964 srclen = strlen(src);
3965 if (*dst == NULL((void *)0) || dstlen + srclen > buflen) {
3966 nbuflen = (((dstlen + srclen) / 512) + 1) * 512;
3967 tmp = recallocarray(*dst, buflen, nbuflen, sizeof(*tmp));
3968 if (tmp == NULL((void *)0))
3969 return -1;
3970 *dst = tmp;
3971 buflen = nbuflen;
3972 }
3973
3974 (void)strlcat(*dst, src, buflen);
3975 return 0;
3976}
3977
3978static int
3979agentx_oidfill(struct ax_oid *oid, const uint32_t oidval[], size_t oidlen,
3980 const char **errstr)
3981{
3982 size_t i;
3983
3984 if (oidlen < AGENTX_OID_MIN_LEN2) {
3985 *errstr = "oidlen < 2";
3986 errno(*__errno()) = EINVAL22;
3987 return -1;
3988 }
3989 if (oidlen > AGENTX_OID_MAX_LEN128) {
3990 *errstr = "oidlen > 128";
3991 errno(*__errno()) = EINVAL22;
3992 return -1;
3993 }
3994
3995 for (i = 0; i < oidlen; i++)
3996 oid->aoi_id[i] = oidval[i];
3997 oid->aoi_idlen = oidlen;
3998 return 0;
3999}
4000
4001void
4002agentx_read(struct agentx *ax)
4003{
4004 struct agentx_session *axs;
4005 struct agentx_context *axc;
4006 struct agentx_request axr_search, *axr;
4007 struct ax_pdu *pdu;
4008 int error;
4009
4010 if ((pdu = ax_recv(ax->ax_ax)) == NULL((void *)0)) {
4011 if (errno(*__errno()) == EAGAIN35)
4012 return;
4013 agentx_log_ax_warn(ax, "lost connection");
4014 agentx_reset(ax);
4015 return;
4016 }
4017
4018 TAILQ_FOREACH(axs, &(ax->ax_sessions), axs_ax_sessions)for((axs) = ((&(ax->ax_sessions))->tqh_first); (axs
) != ((void *)0); (axs) = ((axs)->axs_ax_sessions.tqe_next
))
{
4019 if (axs->axs_id == pdu->ap_header.aph_sessionid)
4020 break;
4021 if (axs->axs_cstate == AX_CSTATE_WAITOPEN &&
4022 axs->axs_packetid == pdu->ap_header.aph_packetid)
4023 break;
4024 }
4025 if (axs == NULL((void *)0)) {
4026 agentx_log_ax_warnx(ax, "received unexpected session: %d",
4027 pdu->ap_header.aph_sessionid);
4028 ax_pdu_free(pdu);
4029 agentx_reset(ax);
4030 return;
4031 }
4032 TAILQ_FOREACH(axc, &(axs->axs_contexts), axc_axs_contexts)for((axc) = ((&(axs->axs_contexts))->tqh_first); (axc
) != ((void *)0); (axc) = ((axc)->axc_axs_contexts.tqe_next
))
{
4033 if ((pdu->ap_header.aph_flags &
4034 AX_PDU_FLAG_NON_DEFAULT_CONTEXT(1 << 3)) == 0 &&
4035 axc->axc_name_default == 1)
4036 break;
4037 if (pdu->ap_header.aph_flags &
4038 AX_PDU_FLAG_NON_DEFAULT_CONTEXT(1 << 3) &&
4039 axc->axc_name_default == 0 &&
4040 pdu->ap_context.aos_slen == axc->axc_name.aos_slen &&
4041 memcmp(pdu->ap_context.aos_string,
4042 axc->axc_name.aos_string, axc->axc_name.aos_slen) == 0)
4043 break;
4044 }
4045 if (pdu->ap_header.aph_type != AX_PDU_TYPE_RESPONSE) {
4046 if (axc == NULL((void *)0)) {
4047 agentx_log_ax_warnx(ax, "%s: invalid context",
4048 pdu->ap_context.aos_string);
4049 ax_pdu_free(pdu);
4050 agentx_reset(ax);
4051 return;
4052 }
4053 }
4054
4055 switch (pdu->ap_header.aph_type) {
4056 case AX_PDU_TYPE_GET:
4057 case AX_PDU_TYPE_GETNEXT:
4058 case AX_PDU_TYPE_GETBULK:
4059 agentx_get_start(axc, pdu);
4060 break;
4061 /* Add stubs for set functions */
4062 case AX_PDU_TYPE_TESTSET:
4063 case AX_PDU_TYPE_COMMITSET:
4064 case AX_PDU_TYPE_UNDOSET:
4065 if (pdu->ap_header.aph_type == AX_PDU_TYPE_TESTSET)
4066 error = AX_PDU_ERROR_NOTWRITABLE;
4067 else if (pdu->ap_header.aph_type == AX_PDU_TYPE_COMMITSET)
4068 error = AX_PDU_ERROR_COMMITFAILED;
4069 else
4070 error = AX_PDU_ERROR_UNDOFAILED;
4071
4072 agentx_log_axc_debug(axc, "unsupported call: %s",
4073 ax_pdutype2string(pdu->ap_header.aph_type));
4074 if (ax_response(ax->ax_ax, axs->axs_id,
4075 pdu->ap_header.aph_transactionid,
4076 pdu->ap_header.aph_packetid,
4077 0, error, 1, NULL((void *)0), 0) == -1)
4078 agentx_log_axc_warn(axc,
4079 "transaction: %u packetid: %u: failed to send "
4080 "reply", pdu->ap_header.aph_transactionid,
4081 pdu->ap_header.aph_packetid);
4082 if (ax->ax_ax->ax_wblen > 0)
4083 agentx_wantwrite(ax, ax->ax_fd);
4084 break;
4085 case AX_PDU_TYPE_CLEANUPSET:
4086 agentx_log_ax_debug(ax, "unsupported call: %s",
4087 ax_pdutype2string(pdu->ap_header.aph_type));
4088 break;
4089 case AX_PDU_TYPE_RESPONSE:
4090 axr_search.axr_packetid = pdu->ap_header.aph_packetid;
4091 axr = RB_FIND(ax_requests, &(ax->ax_requests), &axr_search)ax_requests_RB_FIND(&(ax->ax_requests), &axr_search
)
;
4092 if (axr == NULL((void *)0)) {
4093 if (axc == NULL((void *)0))
4094 agentx_log_ax_warnx(ax, "received "
4095 "response on non-request");
4096 else
4097 agentx_log_axc_warnx(axc, "received "
4098 "response on non-request");
4099 break;
4100 }
4101 if (axc != NULL((void *)0) && pdu->ap_payload.ap_response.ap_error == 0) {
4102 axc->axc_sysuptime =
4103 pdu->ap_payload.ap_response.ap_uptime;
4104 (void) clock_gettime(CLOCK_MONOTONIC3,
4105 &(axc->axc_sysuptimespec));
4106 }
4107 RB_REMOVE(ax_requests, &(ax->ax_requests), axr)ax_requests_RB_REMOVE(&(ax->ax_requests), axr);
4108 (void) axr->axr_cb(pdu, axr->axr_cookie);
4109 free(axr);
4110 break;
4111 default:
4112 if (axc == NULL((void *)0))
4113 agentx_log_ax_warnx(ax, "unsupported call: %s",
4114 ax_pdutype2string(pdu->ap_header.aph_type));
4115 else
4116 agentx_log_axc_warnx(axc, "unsupported call: %s",
4117 ax_pdutype2string(pdu->ap_header.aph_type));
4118 agentx_reset(ax);
4119 break;
4120 }
4121 ax_pdu_free(pdu);
4122}
4123
4124void
4125agentx_write(struct agentx *ax)
4126{
4127 ssize_t send;
4128
4129 if ((send = ax_send(ax->ax_ax)) == -1) {
4130 if (errno(*__errno()) == EAGAIN35) {
4131 agentx_wantwrite(ax, ax->ax_fd);
4132 return;
4133 }
4134 agentx_log_ax_warn(ax, "lost connection");
4135 agentx_reset(ax);
4136 return;
4137 }
4138 if (send > 0)
4139 agentx_wantwrite(ax, ax->ax_fd);
4140}
4141
4142RB_GENERATE_STATIC(ax_requests, agentx_request, axr_ax_requests,__attribute__((__unused__)) static void ax_requests_RB_INSERT_COLOR
(struct ax_requests *head, struct agentx_request *elm) { struct
agentx_request *parent, *gparent, *tmp; while ((parent = (elm
)->axr_ax_requests.rbe_parent) && (parent)->axr_ax_requests
.rbe_color == 1) { gparent = (parent)->axr_ax_requests.rbe_parent
; if (parent == (gparent)->axr_ax_requests.rbe_left) { tmp
= (gparent)->axr_ax_requests.rbe_right; if (tmp &&
(tmp)->axr_ax_requests.rbe_color == 1) { (tmp)->axr_ax_requests
.rbe_color = 0; do { (parent)->axr_ax_requests.rbe_color =
0; (gparent)->axr_ax_requests.rbe_color = 1; } while (0);
elm = gparent; continue; } if ((parent)->axr_ax_requests.
rbe_right == elm) { do { (tmp) = (parent)->axr_ax_requests
.rbe_right; if (((parent)->axr_ax_requests.rbe_right = (tmp
)->axr_ax_requests.rbe_left)) { ((tmp)->axr_ax_requests
.rbe_left)->axr_ax_requests.rbe_parent = (parent); } do {}
while (0); if (((tmp)->axr_ax_requests.rbe_parent = (parent
)->axr_ax_requests.rbe_parent)) { if ((parent) == ((parent
)->axr_ax_requests.rbe_parent)->axr_ax_requests.rbe_left
) ((parent)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left = (tmp); else ((parent)->axr_ax_requests.rbe_parent
)->axr_ax_requests.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axr_ax_requests.rbe_left = (parent); (parent
)->axr_ax_requests.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axr_ax_requests.rbe_parent)) do {} while (0); } while
(0); tmp = parent; parent = elm; elm = tmp; } do { (parent)->
axr_ax_requests.rbe_color = 0; (gparent)->axr_ax_requests.
rbe_color = 1; } while (0); do { (tmp) = (gparent)->axr_ax_requests
.rbe_left; if (((gparent)->axr_ax_requests.rbe_left = (tmp
)->axr_ax_requests.rbe_right)) { ((tmp)->axr_ax_requests
.rbe_right)->axr_ax_requests.rbe_parent = (gparent); } do {
} while (0); if (((tmp)->axr_ax_requests.rbe_parent = (gparent
)->axr_ax_requests.rbe_parent)) { if ((gparent) == ((gparent
)->axr_ax_requests.rbe_parent)->axr_ax_requests.rbe_left
) ((gparent)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left = (tmp); else ((gparent)->axr_ax_requests.rbe_parent
)->axr_ax_requests.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axr_ax_requests.rbe_right = (gparent); (gparent
)->axr_ax_requests.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axr_ax_requests.rbe_parent)) do {} while (0); } while
(0); } else { tmp = (gparent)->axr_ax_requests.rbe_left; if
(tmp && (tmp)->axr_ax_requests.rbe_color == 1) { (
tmp)->axr_ax_requests.rbe_color = 0; do { (parent)->axr_ax_requests
.rbe_color = 0; (gparent)->axr_ax_requests.rbe_color = 1; }
while (0); elm = gparent; continue; } if ((parent)->axr_ax_requests
.rbe_left == elm) { do { (tmp) = (parent)->axr_ax_requests
.rbe_left; if (((parent)->axr_ax_requests.rbe_left = (tmp)
->axr_ax_requests.rbe_right)) { ((tmp)->axr_ax_requests
.rbe_right)->axr_ax_requests.rbe_parent = (parent); } do {
} while (0); if (((tmp)->axr_ax_requests.rbe_parent = (parent
)->axr_ax_requests.rbe_parent)) { if ((parent) == ((parent
)->axr_ax_requests.rbe_parent)->axr_ax_requests.rbe_left
) ((parent)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left = (tmp); else ((parent)->axr_ax_requests.rbe_parent
)->axr_ax_requests.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axr_ax_requests.rbe_right = (parent); (parent
)->axr_ax_requests.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axr_ax_requests.rbe_parent)) do {} while (0); } while
(0); tmp = parent; parent = elm; elm = tmp; } do { (parent)->
axr_ax_requests.rbe_color = 0; (gparent)->axr_ax_requests.
rbe_color = 1; } while (0); do { (tmp) = (gparent)->axr_ax_requests
.rbe_right; if (((gparent)->axr_ax_requests.rbe_right = (tmp
)->axr_ax_requests.rbe_left)) { ((tmp)->axr_ax_requests
.rbe_left)->axr_ax_requests.rbe_parent = (gparent); } do {
} while (0); if (((tmp)->axr_ax_requests.rbe_parent = (gparent
)->axr_ax_requests.rbe_parent)) { if ((gparent) == ((gparent
)->axr_ax_requests.rbe_parent)->axr_ax_requests.rbe_left
) ((gparent)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left = (tmp); else ((gparent)->axr_ax_requests.rbe_parent
)->axr_ax_requests.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axr_ax_requests.rbe_left = (gparent); (gparent
)->axr_ax_requests.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axr_ax_requests.rbe_parent)) do {} while (0); } while
(0); } } (head->rbh_root)->axr_ax_requests.rbe_color =
0; } __attribute__((__unused__)) static void ax_requests_RB_REMOVE_COLOR
(struct ax_requests *head, struct agentx_request *parent, struct
agentx_request *elm) { struct agentx_request *tmp; while ((elm
== ((void *)0) || (elm)->axr_ax_requests.rbe_color == 0) &&
elm != (head)->rbh_root) { if ((parent)->axr_ax_requests
.rbe_left == elm) { tmp = (parent)->axr_ax_requests.rbe_right
; if ((tmp)->axr_ax_requests.rbe_color == 1) { do { (tmp)->
axr_ax_requests.rbe_color = 0; (parent)->axr_ax_requests.rbe_color
= 1; } while (0); do { (tmp) = (parent)->axr_ax_requests.
rbe_right; if (((parent)->axr_ax_requests.rbe_right = (tmp
)->axr_ax_requests.rbe_left)) { ((tmp)->axr_ax_requests
.rbe_left)->axr_ax_requests.rbe_parent = (parent); } do {}
while (0); if (((tmp)->axr_ax_requests.rbe_parent = (parent
)->axr_ax_requests.rbe_parent)) { if ((parent) == ((parent
)->axr_ax_requests.rbe_parent)->axr_ax_requests.rbe_left
) ((parent)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left = (tmp); else ((parent)->axr_ax_requests.rbe_parent
)->axr_ax_requests.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axr_ax_requests.rbe_left = (parent); (parent
)->axr_ax_requests.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axr_ax_requests.rbe_parent)) do {} while (0); } while
(0); tmp = (parent)->axr_ax_requests.rbe_right; } if (((tmp
)->axr_ax_requests.rbe_left == ((void *)0) || ((tmp)->axr_ax_requests
.rbe_left)->axr_ax_requests.rbe_color == 0) && ((tmp
)->axr_ax_requests.rbe_right == ((void *)0) || ((tmp)->
axr_ax_requests.rbe_right)->axr_ax_requests.rbe_color == 0
)) { (tmp)->axr_ax_requests.rbe_color = 1; elm = parent; parent
= (elm)->axr_ax_requests.rbe_parent; } else { if ((tmp)->
axr_ax_requests.rbe_right == ((void *)0) || ((tmp)->axr_ax_requests
.rbe_right)->axr_ax_requests.rbe_color == 0) { struct agentx_request
*oleft; if ((oleft = (tmp)->axr_ax_requests.rbe_left)) (oleft
)->axr_ax_requests.rbe_color = 0; (tmp)->axr_ax_requests
.rbe_color = 1; do { (oleft) = (tmp)->axr_ax_requests.rbe_left
; if (((tmp)->axr_ax_requests.rbe_left = (oleft)->axr_ax_requests
.rbe_right)) { ((oleft)->axr_ax_requests.rbe_right)->axr_ax_requests
.rbe_parent = (tmp); } do {} while (0); if (((oleft)->axr_ax_requests
.rbe_parent = (tmp)->axr_ax_requests.rbe_parent)) { if ((tmp
) == ((tmp)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left) ((tmp)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left = (oleft); else ((tmp)->axr_ax_requests.rbe_parent
)->axr_ax_requests.rbe_right = (oleft); } else (head)->
rbh_root = (oleft); (oleft)->axr_ax_requests.rbe_right = (
tmp); (tmp)->axr_ax_requests.rbe_parent = (oleft); do {} while
(0); if (((oleft)->axr_ax_requests.rbe_parent)) do {} while
(0); } while (0); tmp = (parent)->axr_ax_requests.rbe_right
; } (tmp)->axr_ax_requests.rbe_color = (parent)->axr_ax_requests
.rbe_color; (parent)->axr_ax_requests.rbe_color = 0; if ((
tmp)->axr_ax_requests.rbe_right) ((tmp)->axr_ax_requests
.rbe_right)->axr_ax_requests.rbe_color = 0; do { (tmp) = (
parent)->axr_ax_requests.rbe_right; if (((parent)->axr_ax_requests
.rbe_right = (tmp)->axr_ax_requests.rbe_left)) { ((tmp)->
axr_ax_requests.rbe_left)->axr_ax_requests.rbe_parent = (parent
); } do {} while (0); if (((tmp)->axr_ax_requests.rbe_parent
= (parent)->axr_ax_requests.rbe_parent)) { if ((parent) ==
((parent)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left) ((parent)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left = (tmp); else ((parent)->axr_ax_requests.rbe_parent
)->axr_ax_requests.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axr_ax_requests.rbe_left = (parent); (parent
)->axr_ax_requests.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axr_ax_requests.rbe_parent)) do {} while (0); } while
(0); elm = (head)->rbh_root; break; } } else { tmp = (parent
)->axr_ax_requests.rbe_left; if ((tmp)->axr_ax_requests
.rbe_color == 1) { do { (tmp)->axr_ax_requests.rbe_color =
0; (parent)->axr_ax_requests.rbe_color = 1; } while (0); do
{ (tmp) = (parent)->axr_ax_requests.rbe_left; if (((parent
)->axr_ax_requests.rbe_left = (tmp)->axr_ax_requests.rbe_right
)) { ((tmp)->axr_ax_requests.rbe_right)->axr_ax_requests
.rbe_parent = (parent); } do {} while (0); if (((tmp)->axr_ax_requests
.rbe_parent = (parent)->axr_ax_requests.rbe_parent)) { if (
(parent) == ((parent)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left) ((parent)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left = (tmp); else ((parent)->axr_ax_requests.rbe_parent
)->axr_ax_requests.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axr_ax_requests.rbe_right = (parent); (parent
)->axr_ax_requests.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axr_ax_requests.rbe_parent)) do {} while (0); } while
(0); tmp = (parent)->axr_ax_requests.rbe_left; } if (((tmp
)->axr_ax_requests.rbe_left == ((void *)0) || ((tmp)->axr_ax_requests
.rbe_left)->axr_ax_requests.rbe_color == 0) && ((tmp
)->axr_ax_requests.rbe_right == ((void *)0) || ((tmp)->
axr_ax_requests.rbe_right)->axr_ax_requests.rbe_color == 0
)) { (tmp)->axr_ax_requests.rbe_color = 1; elm = parent; parent
= (elm)->axr_ax_requests.rbe_parent; } else { if ((tmp)->
axr_ax_requests.rbe_left == ((void *)0) || ((tmp)->axr_ax_requests
.rbe_left)->axr_ax_requests.rbe_color == 0) { struct agentx_request
*oright; if ((oright = (tmp)->axr_ax_requests.rbe_right))
(oright)->axr_ax_requests.rbe_color = 0; (tmp)->axr_ax_requests
.rbe_color = 1; do { (oright) = (tmp)->axr_ax_requests.rbe_right
; if (((tmp)->axr_ax_requests.rbe_right = (oright)->axr_ax_requests
.rbe_left)) { ((oright)->axr_ax_requests.rbe_left)->axr_ax_requests
.rbe_parent = (tmp); } do {} while (0); if (((oright)->axr_ax_requests
.rbe_parent = (tmp)->axr_ax_requests.rbe_parent)) { if ((tmp
) == ((tmp)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left) ((tmp)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left = (oright); else ((tmp)->axr_ax_requests.rbe_parent
)->axr_ax_requests.rbe_right = (oright); } else (head)->
rbh_root = (oright); (oright)->axr_ax_requests.rbe_left = (
tmp); (tmp)->axr_ax_requests.rbe_parent = (oright); do {} while
(0); if (((oright)->axr_ax_requests.rbe_parent)) do {} while
(0); } while (0); tmp = (parent)->axr_ax_requests.rbe_left
; } (tmp)->axr_ax_requests.rbe_color = (parent)->axr_ax_requests
.rbe_color; (parent)->axr_ax_requests.rbe_color = 0; if ((
tmp)->axr_ax_requests.rbe_left) ((tmp)->axr_ax_requests
.rbe_left)->axr_ax_requests.rbe_color = 0; do { (tmp) = (parent
)->axr_ax_requests.rbe_left; if (((parent)->axr_ax_requests
.rbe_left = (tmp)->axr_ax_requests.rbe_right)) { ((tmp)->
axr_ax_requests.rbe_right)->axr_ax_requests.rbe_parent = (
parent); } do {} while (0); if (((tmp)->axr_ax_requests.rbe_parent
= (parent)->axr_ax_requests.rbe_parent)) { if ((parent) ==
((parent)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left) ((parent)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left = (tmp); else ((parent)->axr_ax_requests.rbe_parent
)->axr_ax_requests.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axr_ax_requests.rbe_right = (parent); (parent
)->axr_ax_requests.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axr_ax_requests.rbe_parent)) do {} while (0); } while
(0); elm = (head)->rbh_root; break; } } } if (elm) (elm)->
axr_ax_requests.rbe_color = 0; } __attribute__((__unused__)) static
struct agentx_request * ax_requests_RB_REMOVE(struct ax_requests
*head, struct agentx_request *elm) { struct agentx_request *
child, *parent, *old = elm; int color; if ((elm)->axr_ax_requests
.rbe_left == ((void *)0)) child = (elm)->axr_ax_requests.rbe_right
; else if ((elm)->axr_ax_requests.rbe_right == ((void *)0)
) child = (elm)->axr_ax_requests.rbe_left; else { struct agentx_request
*left; elm = (elm)->axr_ax_requests.rbe_right; while ((left
= (elm)->axr_ax_requests.rbe_left)) elm = left; child = (
elm)->axr_ax_requests.rbe_right; parent = (elm)->axr_ax_requests
.rbe_parent; color = (elm)->axr_ax_requests.rbe_color; if (
child) (child)->axr_ax_requests.rbe_parent = parent; if (parent
) { if ((parent)->axr_ax_requests.rbe_left == elm) (parent
)->axr_ax_requests.rbe_left = child; else (parent)->axr_ax_requests
.rbe_right = child; do {} while (0); } else (head)->rbh_root
= child; if ((elm)->axr_ax_requests.rbe_parent == old) parent
= elm; (elm)->axr_ax_requests = (old)->axr_ax_requests
; if ((old)->axr_ax_requests.rbe_parent) { if (((old)->
axr_ax_requests.rbe_parent)->axr_ax_requests.rbe_left == old
) ((old)->axr_ax_requests.rbe_parent)->axr_ax_requests.
rbe_left = elm; else ((old)->axr_ax_requests.rbe_parent)->
axr_ax_requests.rbe_right = elm; do {} while (0); } else (head
)->rbh_root = elm; ((old)->axr_ax_requests.rbe_left)->
axr_ax_requests.rbe_parent = elm; if ((old)->axr_ax_requests
.rbe_right) ((old)->axr_ax_requests.rbe_right)->axr_ax_requests
.rbe_parent = elm; if (parent) { left = parent; do { do {} while
(0); } while ((left = (left)->axr_ax_requests.rbe_parent)
); } goto color; } parent = (elm)->axr_ax_requests.rbe_parent
; color = (elm)->axr_ax_requests.rbe_color; if (child) (child
)->axr_ax_requests.rbe_parent = parent; if (parent) { if (
(parent)->axr_ax_requests.rbe_left == elm) (parent)->axr_ax_requests
.rbe_left = child; else (parent)->axr_ax_requests.rbe_right
= child; do {} while (0); } else (head)->rbh_root = child
; color: if (color == 0) ax_requests_RB_REMOVE_COLOR(head, parent
, child); return (old); } __attribute__((__unused__)) static struct
agentx_request * ax_requests_RB_INSERT(struct ax_requests *head
, struct agentx_request *elm) { struct agentx_request *tmp; struct
agentx_request *parent = ((void *)0); int comp = 0; tmp = (head
)->rbh_root; while (tmp) { parent = tmp; comp = (agentx_request_cmp
)(elm, parent); if (comp < 0) tmp = (tmp)->axr_ax_requests
.rbe_left; else if (comp > 0) tmp = (tmp)->axr_ax_requests
.rbe_right; else return (tmp); } do { (elm)->axr_ax_requests
.rbe_parent = parent; (elm)->axr_ax_requests.rbe_left = (elm
)->axr_ax_requests.rbe_right = ((void *)0); (elm)->axr_ax_requests
.rbe_color = 1; } while (0); if (parent != ((void *)0)) { if (
comp < 0) (parent)->axr_ax_requests.rbe_left = elm; else
(parent)->axr_ax_requests.rbe_right = elm; do {} while (0
); } else (head)->rbh_root = elm; ax_requests_RB_INSERT_COLOR
(head, elm); return (((void *)0)); } __attribute__((__unused__
)) static struct agentx_request * ax_requests_RB_FIND(struct ax_requests
*head, struct agentx_request *elm) { struct agentx_request *
tmp = (head)->rbh_root; int comp; while (tmp) { comp = agentx_request_cmp
(elm, tmp); if (comp < 0) tmp = (tmp)->axr_ax_requests.
rbe_left; else if (comp > 0) tmp = (tmp)->axr_ax_requests
.rbe_right; else return (tmp); } return (((void *)0)); } __attribute__
((__unused__)) static struct agentx_request * ax_requests_RB_NFIND
(struct ax_requests *head, struct agentx_request *elm) { struct
agentx_request *tmp = (head)->rbh_root; struct agentx_request
*res = ((void *)0); int comp; while (tmp) { comp = agentx_request_cmp
(elm, tmp); if (comp < 0) { res = tmp; tmp = (tmp)->axr_ax_requests
.rbe_left; } else if (comp > 0) tmp = (tmp)->axr_ax_requests
.rbe_right; else return (tmp); } return (res); } __attribute__
((__unused__)) static struct agentx_request * ax_requests_RB_NEXT
(struct agentx_request *elm) { if ((elm)->axr_ax_requests.
rbe_right) { elm = (elm)->axr_ax_requests.rbe_right; while
((elm)->axr_ax_requests.rbe_left) elm = (elm)->axr_ax_requests
.rbe_left; } else { if ((elm)->axr_ax_requests.rbe_parent &&
(elm == ((elm)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left)) elm = (elm)->axr_ax_requests.rbe_parent; else {
while ((elm)->axr_ax_requests.rbe_parent && (elm ==
((elm)->axr_ax_requests.rbe_parent)->axr_ax_requests.rbe_right
)) elm = (elm)->axr_ax_requests.rbe_parent; elm = (elm)->
axr_ax_requests.rbe_parent; } } return (elm); } __attribute__
((__unused__)) static struct agentx_request * ax_requests_RB_PREV
(struct agentx_request *elm) { if ((elm)->axr_ax_requests.
rbe_left) { elm = (elm)->axr_ax_requests.rbe_left; while (
(elm)->axr_ax_requests.rbe_right) elm = (elm)->axr_ax_requests
.rbe_right; } else { if ((elm)->axr_ax_requests.rbe_parent
&& (elm == ((elm)->axr_ax_requests.rbe_parent)->
axr_ax_requests.rbe_right)) elm = (elm)->axr_ax_requests.rbe_parent
; else { while ((elm)->axr_ax_requests.rbe_parent &&
(elm == ((elm)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left)) elm = (elm)->axr_ax_requests.rbe_parent; elm =
(elm)->axr_ax_requests.rbe_parent; } } return (elm); } __attribute__
((__unused__)) static struct agentx_request * ax_requests_RB_MINMAX
(struct ax_requests *head, int val) { struct agentx_request *
tmp = (head)->rbh_root; struct agentx_request *parent = ((
void *)0); while (tmp) { parent = tmp; if (val < 0) tmp = (
tmp)->axr_ax_requests.rbe_left; else tmp = (tmp)->axr_ax_requests
.rbe_right; } return (parent); }
4143 agentx_request_cmp)__attribute__((__unused__)) static void ax_requests_RB_INSERT_COLOR
(struct ax_requests *head, struct agentx_request *elm) { struct
agentx_request *parent, *gparent, *tmp; while ((parent = (elm
)->axr_ax_requests.rbe_parent) && (parent)->axr_ax_requests
.rbe_color == 1) { gparent = (parent)->axr_ax_requests.rbe_parent
; if (parent == (gparent)->axr_ax_requests.rbe_left) { tmp
= (gparent)->axr_ax_requests.rbe_right; if (tmp &&
(tmp)->axr_ax_requests.rbe_color == 1) { (tmp)->axr_ax_requests
.rbe_color = 0; do { (parent)->axr_ax_requests.rbe_color =
0; (gparent)->axr_ax_requests.rbe_color = 1; } while (0);
elm = gparent; continue; } if ((parent)->axr_ax_requests.
rbe_right == elm) { do { (tmp) = (parent)->axr_ax_requests
.rbe_right; if (((parent)->axr_ax_requests.rbe_right = (tmp
)->axr_ax_requests.rbe_left)) { ((tmp)->axr_ax_requests
.rbe_left)->axr_ax_requests.rbe_parent = (parent); } do {}
while (0); if (((tmp)->axr_ax_requests.rbe_parent = (parent
)->axr_ax_requests.rbe_parent)) { if ((parent) == ((parent
)->axr_ax_requests.rbe_parent)->axr_ax_requests.rbe_left
) ((parent)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left = (tmp); else ((parent)->axr_ax_requests.rbe_parent
)->axr_ax_requests.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axr_ax_requests.rbe_left = (parent); (parent
)->axr_ax_requests.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axr_ax_requests.rbe_parent)) do {} while (0); } while
(0); tmp = parent; parent = elm; elm = tmp; } do { (parent)->
axr_ax_requests.rbe_color = 0; (gparent)->axr_ax_requests.
rbe_color = 1; } while (0); do { (tmp) = (gparent)->axr_ax_requests
.rbe_left; if (((gparent)->axr_ax_requests.rbe_left = (tmp
)->axr_ax_requests.rbe_right)) { ((tmp)->axr_ax_requests
.rbe_right)->axr_ax_requests.rbe_parent = (gparent); } do {
} while (0); if (((tmp)->axr_ax_requests.rbe_parent = (gparent
)->axr_ax_requests.rbe_parent)) { if ((gparent) == ((gparent
)->axr_ax_requests.rbe_parent)->axr_ax_requests.rbe_left
) ((gparent)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left = (tmp); else ((gparent)->axr_ax_requests.rbe_parent
)->axr_ax_requests.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axr_ax_requests.rbe_right = (gparent); (gparent
)->axr_ax_requests.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axr_ax_requests.rbe_parent)) do {} while (0); } while
(0); } else { tmp = (gparent)->axr_ax_requests.rbe_left; if
(tmp && (tmp)->axr_ax_requests.rbe_color == 1) { (
tmp)->axr_ax_requests.rbe_color = 0; do { (parent)->axr_ax_requests
.rbe_color = 0; (gparent)->axr_ax_requests.rbe_color = 1; }
while (0); elm = gparent; continue; } if ((parent)->axr_ax_requests
.rbe_left == elm) { do { (tmp) = (parent)->axr_ax_requests
.rbe_left; if (((parent)->axr_ax_requests.rbe_left = (tmp)
->axr_ax_requests.rbe_right)) { ((tmp)->axr_ax_requests
.rbe_right)->axr_ax_requests.rbe_parent = (parent); } do {
} while (0); if (((tmp)->axr_ax_requests.rbe_parent = (parent
)->axr_ax_requests.rbe_parent)) { if ((parent) == ((parent
)->axr_ax_requests.rbe_parent)->axr_ax_requests.rbe_left
) ((parent)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left = (tmp); else ((parent)->axr_ax_requests.rbe_parent
)->axr_ax_requests.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axr_ax_requests.rbe_right = (parent); (parent
)->axr_ax_requests.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axr_ax_requests.rbe_parent)) do {} while (0); } while
(0); tmp = parent; parent = elm; elm = tmp; } do { (parent)->
axr_ax_requests.rbe_color = 0; (gparent)->axr_ax_requests.
rbe_color = 1; } while (0); do { (tmp) = (gparent)->axr_ax_requests
.rbe_right; if (((gparent)->axr_ax_requests.rbe_right = (tmp
)->axr_ax_requests.rbe_left)) { ((tmp)->axr_ax_requests
.rbe_left)->axr_ax_requests.rbe_parent = (gparent); } do {
} while (0); if (((tmp)->axr_ax_requests.rbe_parent = (gparent
)->axr_ax_requests.rbe_parent)) { if ((gparent) == ((gparent
)->axr_ax_requests.rbe_parent)->axr_ax_requests.rbe_left
) ((gparent)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left = (tmp); else ((gparent)->axr_ax_requests.rbe_parent
)->axr_ax_requests.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axr_ax_requests.rbe_left = (gparent); (gparent
)->axr_ax_requests.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axr_ax_requests.rbe_parent)) do {} while (0); } while
(0); } } (head->rbh_root)->axr_ax_requests.rbe_color =
0; } __attribute__((__unused__)) static void ax_requests_RB_REMOVE_COLOR
(struct ax_requests *head, struct agentx_request *parent, struct
agentx_request *elm) { struct agentx_request *tmp; while ((elm
== ((void *)0) || (elm)->axr_ax_requests.rbe_color == 0) &&
elm != (head)->rbh_root) { if ((parent)->axr_ax_requests
.rbe_left == elm) { tmp = (parent)->axr_ax_requests.rbe_right
; if ((tmp)->axr_ax_requests.rbe_color == 1) { do { (tmp)->
axr_ax_requests.rbe_color = 0; (parent)->axr_ax_requests.rbe_color
= 1; } while (0); do { (tmp) = (parent)->axr_ax_requests.
rbe_right; if (((parent)->axr_ax_requests.rbe_right = (tmp
)->axr_ax_requests.rbe_left)) { ((tmp)->axr_ax_requests
.rbe_left)->axr_ax_requests.rbe_parent = (parent); } do {}
while (0); if (((tmp)->axr_ax_requests.rbe_parent = (parent
)->axr_ax_requests.rbe_parent)) { if ((parent) == ((parent
)->axr_ax_requests.rbe_parent)->axr_ax_requests.rbe_left
) ((parent)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left = (tmp); else ((parent)->axr_ax_requests.rbe_parent
)->axr_ax_requests.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axr_ax_requests.rbe_left = (parent); (parent
)->axr_ax_requests.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axr_ax_requests.rbe_parent)) do {} while (0); } while
(0); tmp = (parent)->axr_ax_requests.rbe_right; } if (((tmp
)->axr_ax_requests.rbe_left == ((void *)0) || ((tmp)->axr_ax_requests
.rbe_left)->axr_ax_requests.rbe_color == 0) && ((tmp
)->axr_ax_requests.rbe_right == ((void *)0) || ((tmp)->
axr_ax_requests.rbe_right)->axr_ax_requests.rbe_color == 0
)) { (tmp)->axr_ax_requests.rbe_color = 1; elm = parent; parent
= (elm)->axr_ax_requests.rbe_parent; } else { if ((tmp)->
axr_ax_requests.rbe_right == ((void *)0) || ((tmp)->axr_ax_requests
.rbe_right)->axr_ax_requests.rbe_color == 0) { struct agentx_request
*oleft; if ((oleft = (tmp)->axr_ax_requests.rbe_left)) (oleft
)->axr_ax_requests.rbe_color = 0; (tmp)->axr_ax_requests
.rbe_color = 1; do { (oleft) = (tmp)->axr_ax_requests.rbe_left
; if (((tmp)->axr_ax_requests.rbe_left = (oleft)->axr_ax_requests
.rbe_right)) { ((oleft)->axr_ax_requests.rbe_right)->axr_ax_requests
.rbe_parent = (tmp); } do {} while (0); if (((oleft)->axr_ax_requests
.rbe_parent = (tmp)->axr_ax_requests.rbe_parent)) { if ((tmp
) == ((tmp)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left) ((tmp)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left = (oleft); else ((tmp)->axr_ax_requests.rbe_parent
)->axr_ax_requests.rbe_right = (oleft); } else (head)->
rbh_root = (oleft); (oleft)->axr_ax_requests.rbe_right = (
tmp); (tmp)->axr_ax_requests.rbe_parent = (oleft); do {} while
(0); if (((oleft)->axr_ax_requests.rbe_parent)) do {} while
(0); } while (0); tmp = (parent)->axr_ax_requests.rbe_right
; } (tmp)->axr_ax_requests.rbe_color = (parent)->axr_ax_requests
.rbe_color; (parent)->axr_ax_requests.rbe_color = 0; if ((
tmp)->axr_ax_requests.rbe_right) ((tmp)->axr_ax_requests
.rbe_right)->axr_ax_requests.rbe_color = 0; do { (tmp) = (
parent)->axr_ax_requests.rbe_right; if (((parent)->axr_ax_requests
.rbe_right = (tmp)->axr_ax_requests.rbe_left)) { ((tmp)->
axr_ax_requests.rbe_left)->axr_ax_requests.rbe_parent = (parent
); } do {} while (0); if (((tmp)->axr_ax_requests.rbe_parent
= (parent)->axr_ax_requests.rbe_parent)) { if ((parent) ==
((parent)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left) ((parent)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left = (tmp); else ((parent)->axr_ax_requests.rbe_parent
)->axr_ax_requests.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axr_ax_requests.rbe_left = (parent); (parent
)->axr_ax_requests.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axr_ax_requests.rbe_parent)) do {} while (0); } while
(0); elm = (head)->rbh_root; break; } } else { tmp = (parent
)->axr_ax_requests.rbe_left; if ((tmp)->axr_ax_requests
.rbe_color == 1) { do { (tmp)->axr_ax_requests.rbe_color =
0; (parent)->axr_ax_requests.rbe_color = 1; } while (0); do
{ (tmp) = (parent)->axr_ax_requests.rbe_left; if (((parent
)->axr_ax_requests.rbe_left = (tmp)->axr_ax_requests.rbe_right
)) { ((tmp)->axr_ax_requests.rbe_right)->axr_ax_requests
.rbe_parent = (parent); } do {} while (0); if (((tmp)->axr_ax_requests
.rbe_parent = (parent)->axr_ax_requests.rbe_parent)) { if (
(parent) == ((parent)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left) ((parent)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left = (tmp); else ((parent)->axr_ax_requests.rbe_parent
)->axr_ax_requests.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axr_ax_requests.rbe_right = (parent); (parent
)->axr_ax_requests.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axr_ax_requests.rbe_parent)) do {} while (0); } while
(0); tmp = (parent)->axr_ax_requests.rbe_left; } if (((tmp
)->axr_ax_requests.rbe_left == ((void *)0) || ((tmp)->axr_ax_requests
.rbe_left)->axr_ax_requests.rbe_color == 0) && ((tmp
)->axr_ax_requests.rbe_right == ((void *)0) || ((tmp)->
axr_ax_requests.rbe_right)->axr_ax_requests.rbe_color == 0
)) { (tmp)->axr_ax_requests.rbe_color = 1; elm = parent; parent
= (elm)->axr_ax_requests.rbe_parent; } else { if ((tmp)->
axr_ax_requests.rbe_left == ((void *)0) || ((tmp)->axr_ax_requests
.rbe_left)->axr_ax_requests.rbe_color == 0) { struct agentx_request
*oright; if ((oright = (tmp)->axr_ax_requests.rbe_right))
(oright)->axr_ax_requests.rbe_color = 0; (tmp)->axr_ax_requests
.rbe_color = 1; do { (oright) = (tmp)->axr_ax_requests.rbe_right
; if (((tmp)->axr_ax_requests.rbe_right = (oright)->axr_ax_requests
.rbe_left)) { ((oright)->axr_ax_requests.rbe_left)->axr_ax_requests
.rbe_parent = (tmp); } do {} while (0); if (((oright)->axr_ax_requests
.rbe_parent = (tmp)->axr_ax_requests.rbe_parent)) { if ((tmp
) == ((tmp)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left) ((tmp)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left = (oright); else ((tmp)->axr_ax_requests.rbe_parent
)->axr_ax_requests.rbe_right = (oright); } else (head)->
rbh_root = (oright); (oright)->axr_ax_requests.rbe_left = (
tmp); (tmp)->axr_ax_requests.rbe_parent = (oright); do {} while
(0); if (((oright)->axr_ax_requests.rbe_parent)) do {} while
(0); } while (0); tmp = (parent)->axr_ax_requests.rbe_left
; } (tmp)->axr_ax_requests.rbe_color = (parent)->axr_ax_requests
.rbe_color; (parent)->axr_ax_requests.rbe_color = 0; if ((
tmp)->axr_ax_requests.rbe_left) ((tmp)->axr_ax_requests
.rbe_left)->axr_ax_requests.rbe_color = 0; do { (tmp) = (parent
)->axr_ax_requests.rbe_left; if (((parent)->axr_ax_requests
.rbe_left = (tmp)->axr_ax_requests.rbe_right)) { ((tmp)->
axr_ax_requests.rbe_right)->axr_ax_requests.rbe_parent = (
parent); } do {} while (0); if (((tmp)->axr_ax_requests.rbe_parent
= (parent)->axr_ax_requests.rbe_parent)) { if ((parent) ==
((parent)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left) ((parent)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left = (tmp); else ((parent)->axr_ax_requests.rbe_parent
)->axr_ax_requests.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axr_ax_requests.rbe_right = (parent); (parent
)->axr_ax_requests.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axr_ax_requests.rbe_parent)) do {} while (0); } while
(0); elm = (head)->rbh_root; break; } } } if (elm) (elm)->
axr_ax_requests.rbe_color = 0; } __attribute__((__unused__)) static
struct agentx_request * ax_requests_RB_REMOVE(struct ax_requests
*head, struct agentx_request *elm) { struct agentx_request *
child, *parent, *old = elm; int color; if ((elm)->axr_ax_requests
.rbe_left == ((void *)0)) child = (elm)->axr_ax_requests.rbe_right
; else if ((elm)->axr_ax_requests.rbe_right == ((void *)0)
) child = (elm)->axr_ax_requests.rbe_left; else { struct agentx_request
*left; elm = (elm)->axr_ax_requests.rbe_right; while ((left
= (elm)->axr_ax_requests.rbe_left)) elm = left; child = (
elm)->axr_ax_requests.rbe_right; parent = (elm)->axr_ax_requests
.rbe_parent; color = (elm)->axr_ax_requests.rbe_color; if (
child) (child)->axr_ax_requests.rbe_parent = parent; if (parent
) { if ((parent)->axr_ax_requests.rbe_left == elm) (parent
)->axr_ax_requests.rbe_left = child; else (parent)->axr_ax_requests
.rbe_right = child; do {} while (0); } else (head)->rbh_root
= child; if ((elm)->axr_ax_requests.rbe_parent == old) parent
= elm; (elm)->axr_ax_requests = (old)->axr_ax_requests
; if ((old)->axr_ax_requests.rbe_parent) { if (((old)->
axr_ax_requests.rbe_parent)->axr_ax_requests.rbe_left == old
) ((old)->axr_ax_requests.rbe_parent)->axr_ax_requests.
rbe_left = elm; else ((old)->axr_ax_requests.rbe_parent)->
axr_ax_requests.rbe_right = elm; do {} while (0); } else (head
)->rbh_root = elm; ((old)->axr_ax_requests.rbe_left)->
axr_ax_requests.rbe_parent = elm; if ((old)->axr_ax_requests
.rbe_right) ((old)->axr_ax_requests.rbe_right)->axr_ax_requests
.rbe_parent = elm; if (parent) { left = parent; do { do {} while
(0); } while ((left = (left)->axr_ax_requests.rbe_parent)
); } goto color; } parent = (elm)->axr_ax_requests.rbe_parent
; color = (elm)->axr_ax_requests.rbe_color; if (child) (child
)->axr_ax_requests.rbe_parent = parent; if (parent) { if (
(parent)->axr_ax_requests.rbe_left == elm) (parent)->axr_ax_requests
.rbe_left = child; else (parent)->axr_ax_requests.rbe_right
= child; do {} while (0); } else (head)->rbh_root = child
; color: if (color == 0) ax_requests_RB_REMOVE_COLOR(head, parent
, child); return (old); } __attribute__((__unused__)) static struct
agentx_request * ax_requests_RB_INSERT(struct ax_requests *head
, struct agentx_request *elm) { struct agentx_request *tmp; struct
agentx_request *parent = ((void *)0); int comp = 0; tmp = (head
)->rbh_root; while (tmp) { parent = tmp; comp = (agentx_request_cmp
)(elm, parent); if (comp < 0) tmp = (tmp)->axr_ax_requests
.rbe_left; else if (comp > 0) tmp = (tmp)->axr_ax_requests
.rbe_right; else return (tmp); } do { (elm)->axr_ax_requests
.rbe_parent = parent; (elm)->axr_ax_requests.rbe_left = (elm
)->axr_ax_requests.rbe_right = ((void *)0); (elm)->axr_ax_requests
.rbe_color = 1; } while (0); if (parent != ((void *)0)) { if (
comp < 0) (parent)->axr_ax_requests.rbe_left = elm; else
(parent)->axr_ax_requests.rbe_right = elm; do {} while (0
); } else (head)->rbh_root = elm; ax_requests_RB_INSERT_COLOR
(head, elm); return (((void *)0)); } __attribute__((__unused__
)) static struct agentx_request * ax_requests_RB_FIND(struct ax_requests
*head, struct agentx_request *elm) { struct agentx_request *
tmp = (head)->rbh_root; int comp; while (tmp) { comp = agentx_request_cmp
(elm, tmp); if (comp < 0) tmp = (tmp)->axr_ax_requests.
rbe_left; else if (comp > 0) tmp = (tmp)->axr_ax_requests
.rbe_right; else return (tmp); } return (((void *)0)); } __attribute__
((__unused__)) static struct agentx_request * ax_requests_RB_NFIND
(struct ax_requests *head, struct agentx_request *elm) { struct
agentx_request *tmp = (head)->rbh_root; struct agentx_request
*res = ((void *)0); int comp; while (tmp) { comp = agentx_request_cmp
(elm, tmp); if (comp < 0) { res = tmp; tmp = (tmp)->axr_ax_requests
.rbe_left; } else if (comp > 0) tmp = (tmp)->axr_ax_requests
.rbe_right; else return (tmp); } return (res); } __attribute__
((__unused__)) static struct agentx_request * ax_requests_RB_NEXT
(struct agentx_request *elm) { if ((elm)->axr_ax_requests.
rbe_right) { elm = (elm)->axr_ax_requests.rbe_right; while
((elm)->axr_ax_requests.rbe_left) elm = (elm)->axr_ax_requests
.rbe_left; } else { if ((elm)->axr_ax_requests.rbe_parent &&
(elm == ((elm)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left)) elm = (elm)->axr_ax_requests.rbe_parent; else {
while ((elm)->axr_ax_requests.rbe_parent && (elm ==
((elm)->axr_ax_requests.rbe_parent)->axr_ax_requests.rbe_right
)) elm = (elm)->axr_ax_requests.rbe_parent; elm = (elm)->
axr_ax_requests.rbe_parent; } } return (elm); } __attribute__
((__unused__)) static struct agentx_request * ax_requests_RB_PREV
(struct agentx_request *elm) { if ((elm)->axr_ax_requests.
rbe_left) { elm = (elm)->axr_ax_requests.rbe_left; while (
(elm)->axr_ax_requests.rbe_right) elm = (elm)->axr_ax_requests
.rbe_right; } else { if ((elm)->axr_ax_requests.rbe_parent
&& (elm == ((elm)->axr_ax_requests.rbe_parent)->
axr_ax_requests.rbe_right)) elm = (elm)->axr_ax_requests.rbe_parent
; else { while ((elm)->axr_ax_requests.rbe_parent &&
(elm == ((elm)->axr_ax_requests.rbe_parent)->axr_ax_requests
.rbe_left)) elm = (elm)->axr_ax_requests.rbe_parent; elm =
(elm)->axr_ax_requests.rbe_parent; } } return (elm); } __attribute__
((__unused__)) static struct agentx_request * ax_requests_RB_MINMAX
(struct ax_requests *head, int val) { struct agentx_request *
tmp = (head)->rbh_root; struct agentx_request *parent = ((
void *)0); while (tmp) { parent = tmp; if (val < 0) tmp = (
tmp)->axr_ax_requests.rbe_left; else tmp = (tmp)->axr_ax_requests
.rbe_right; } return (parent); }
4144RB_GENERATE_STATIC(axc_objects, agentx_object, axo_axc_objects,__attribute__((__unused__)) static void axc_objects_RB_INSERT_COLOR
(struct axc_objects *head, struct agentx_object *elm) { struct
agentx_object *parent, *gparent, *tmp; while ((parent = (elm
)->axo_axc_objects.rbe_parent) && (parent)->axo_axc_objects
.rbe_color == 1) { gparent = (parent)->axo_axc_objects.rbe_parent
; if (parent == (gparent)->axo_axc_objects.rbe_left) { tmp
= (gparent)->axo_axc_objects.rbe_right; if (tmp &&
(tmp)->axo_axc_objects.rbe_color == 1) { (tmp)->axo_axc_objects
.rbe_color = 0; do { (parent)->axo_axc_objects.rbe_color =
0; (gparent)->axo_axc_objects.rbe_color = 1; } while (0);
elm = gparent; continue; } if ((parent)->axo_axc_objects.
rbe_right == elm) { do { (tmp) = (parent)->axo_axc_objects
.rbe_right; if (((parent)->axo_axc_objects.rbe_right = (tmp
)->axo_axc_objects.rbe_left)) { ((tmp)->axo_axc_objects
.rbe_left)->axo_axc_objects.rbe_parent = (parent); } do {}
while (0); if (((tmp)->axo_axc_objects.rbe_parent = (parent
)->axo_axc_objects.rbe_parent)) { if ((parent) == ((parent
)->axo_axc_objects.rbe_parent)->axo_axc_objects.rbe_left
) ((parent)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left = (tmp); else ((parent)->axo_axc_objects.rbe_parent
)->axo_axc_objects.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axo_axc_objects.rbe_left = (parent); (parent
)->axo_axc_objects.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axo_axc_objects.rbe_parent)) do {} while (0); } while
(0); tmp = parent; parent = elm; elm = tmp; } do { (parent)->
axo_axc_objects.rbe_color = 0; (gparent)->axo_axc_objects.
rbe_color = 1; } while (0); do { (tmp) = (gparent)->axo_axc_objects
.rbe_left; if (((gparent)->axo_axc_objects.rbe_left = (tmp
)->axo_axc_objects.rbe_right)) { ((tmp)->axo_axc_objects
.rbe_right)->axo_axc_objects.rbe_parent = (gparent); } do {
} while (0); if (((tmp)->axo_axc_objects.rbe_parent = (gparent
)->axo_axc_objects.rbe_parent)) { if ((gparent) == ((gparent
)->axo_axc_objects.rbe_parent)->axo_axc_objects.rbe_left
) ((gparent)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left = (tmp); else ((gparent)->axo_axc_objects.rbe_parent
)->axo_axc_objects.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axo_axc_objects.rbe_right = (gparent); (gparent
)->axo_axc_objects.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axo_axc_objects.rbe_parent)) do {} while (0); } while
(0); } else { tmp = (gparent)->axo_axc_objects.rbe_left; if
(tmp && (tmp)->axo_axc_objects.rbe_color == 1) { (
tmp)->axo_axc_objects.rbe_color = 0; do { (parent)->axo_axc_objects
.rbe_color = 0; (gparent)->axo_axc_objects.rbe_color = 1; }
while (0); elm = gparent; continue; } if ((parent)->axo_axc_objects
.rbe_left == elm) { do { (tmp) = (parent)->axo_axc_objects
.rbe_left; if (((parent)->axo_axc_objects.rbe_left = (tmp)
->axo_axc_objects.rbe_right)) { ((tmp)->axo_axc_objects
.rbe_right)->axo_axc_objects.rbe_parent = (parent); } do {
} while (0); if (((tmp)->axo_axc_objects.rbe_parent = (parent
)->axo_axc_objects.rbe_parent)) { if ((parent) == ((parent
)->axo_axc_objects.rbe_parent)->axo_axc_objects.rbe_left
) ((parent)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left = (tmp); else ((parent)->axo_axc_objects.rbe_parent
)->axo_axc_objects.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axo_axc_objects.rbe_right = (parent); (parent
)->axo_axc_objects.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axo_axc_objects.rbe_parent)) do {} while (0); } while
(0); tmp = parent; parent = elm; elm = tmp; } do { (parent)->
axo_axc_objects.rbe_color = 0; (gparent)->axo_axc_objects.
rbe_color = 1; } while (0); do { (tmp) = (gparent)->axo_axc_objects
.rbe_right; if (((gparent)->axo_axc_objects.rbe_right = (tmp
)->axo_axc_objects.rbe_left)) { ((tmp)->axo_axc_objects
.rbe_left)->axo_axc_objects.rbe_parent = (gparent); } do {
} while (0); if (((tmp)->axo_axc_objects.rbe_parent = (gparent
)->axo_axc_objects.rbe_parent)) { if ((gparent) == ((gparent
)->axo_axc_objects.rbe_parent)->axo_axc_objects.rbe_left
) ((gparent)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left = (tmp); else ((gparent)->axo_axc_objects.rbe_parent
)->axo_axc_objects.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axo_axc_objects.rbe_left = (gparent); (gparent
)->axo_axc_objects.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axo_axc_objects.rbe_parent)) do {} while (0); } while
(0); } } (head->rbh_root)->axo_axc_objects.rbe_color =
0; } __attribute__((__unused__)) static void axc_objects_RB_REMOVE_COLOR
(struct axc_objects *head, struct agentx_object *parent, struct
agentx_object *elm) { struct agentx_object *tmp; while ((elm
== ((void *)0) || (elm)->axo_axc_objects.rbe_color == 0) &&
elm != (head)->rbh_root) { if ((parent)->axo_axc_objects
.rbe_left == elm) { tmp = (parent)->axo_axc_objects.rbe_right
; if ((tmp)->axo_axc_objects.rbe_color == 1) { do { (tmp)->
axo_axc_objects.rbe_color = 0; (parent)->axo_axc_objects.rbe_color
= 1; } while (0); do { (tmp) = (parent)->axo_axc_objects.
rbe_right; if (((parent)->axo_axc_objects.rbe_right = (tmp
)->axo_axc_objects.rbe_left)) { ((tmp)->axo_axc_objects
.rbe_left)->axo_axc_objects.rbe_parent = (parent); } do {}
while (0); if (((tmp)->axo_axc_objects.rbe_parent = (parent
)->axo_axc_objects.rbe_parent)) { if ((parent) == ((parent
)->axo_axc_objects.rbe_parent)->axo_axc_objects.rbe_left
) ((parent)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left = (tmp); else ((parent)->axo_axc_objects.rbe_parent
)->axo_axc_objects.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axo_axc_objects.rbe_left = (parent); (parent
)->axo_axc_objects.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axo_axc_objects.rbe_parent)) do {} while (0); } while
(0); tmp = (parent)->axo_axc_objects.rbe_right; } if (((tmp
)->axo_axc_objects.rbe_left == ((void *)0) || ((tmp)->axo_axc_objects
.rbe_left)->axo_axc_objects.rbe_color == 0) && ((tmp
)->axo_axc_objects.rbe_right == ((void *)0) || ((tmp)->
axo_axc_objects.rbe_right)->axo_axc_objects.rbe_color == 0
)) { (tmp)->axo_axc_objects.rbe_color = 1; elm = parent; parent
= (elm)->axo_axc_objects.rbe_parent; } else { if ((tmp)->
axo_axc_objects.rbe_right == ((void *)0) || ((tmp)->axo_axc_objects
.rbe_right)->axo_axc_objects.rbe_color == 0) { struct agentx_object
*oleft; if ((oleft = (tmp)->axo_axc_objects.rbe_left)) (oleft
)->axo_axc_objects.rbe_color = 0; (tmp)->axo_axc_objects
.rbe_color = 1; do { (oleft) = (tmp)->axo_axc_objects.rbe_left
; if (((tmp)->axo_axc_objects.rbe_left = (oleft)->axo_axc_objects
.rbe_right)) { ((oleft)->axo_axc_objects.rbe_right)->axo_axc_objects
.rbe_parent = (tmp); } do {} while (0); if (((oleft)->axo_axc_objects
.rbe_parent = (tmp)->axo_axc_objects.rbe_parent)) { if ((tmp
) == ((tmp)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left) ((tmp)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left = (oleft); else ((tmp)->axo_axc_objects.rbe_parent
)->axo_axc_objects.rbe_right = (oleft); } else (head)->
rbh_root = (oleft); (oleft)->axo_axc_objects.rbe_right = (
tmp); (tmp)->axo_axc_objects.rbe_parent = (oleft); do {} while
(0); if (((oleft)->axo_axc_objects.rbe_parent)) do {} while
(0); } while (0); tmp = (parent)->axo_axc_objects.rbe_right
; } (tmp)->axo_axc_objects.rbe_color = (parent)->axo_axc_objects
.rbe_color; (parent)->axo_axc_objects.rbe_color = 0; if ((
tmp)->axo_axc_objects.rbe_right) ((tmp)->axo_axc_objects
.rbe_right)->axo_axc_objects.rbe_color = 0; do { (tmp) = (
parent)->axo_axc_objects.rbe_right; if (((parent)->axo_axc_objects
.rbe_right = (tmp)->axo_axc_objects.rbe_left)) { ((tmp)->
axo_axc_objects.rbe_left)->axo_axc_objects.rbe_parent = (parent
); } do {} while (0); if (((tmp)->axo_axc_objects.rbe_parent
= (parent)->axo_axc_objects.rbe_parent)) { if ((parent) ==
((parent)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left) ((parent)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left = (tmp); else ((parent)->axo_axc_objects.rbe_parent
)->axo_axc_objects.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axo_axc_objects.rbe_left = (parent); (parent
)->axo_axc_objects.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axo_axc_objects.rbe_parent)) do {} while (0); } while
(0); elm = (head)->rbh_root; break; } } else { tmp = (parent
)->axo_axc_objects.rbe_left; if ((tmp)->axo_axc_objects
.rbe_color == 1) { do { (tmp)->axo_axc_objects.rbe_color =
0; (parent)->axo_axc_objects.rbe_color = 1; } while (0); do
{ (tmp) = (parent)->axo_axc_objects.rbe_left; if (((parent
)->axo_axc_objects.rbe_left = (tmp)->axo_axc_objects.rbe_right
)) { ((tmp)->axo_axc_objects.rbe_right)->axo_axc_objects
.rbe_parent = (parent); } do {} while (0); if (((tmp)->axo_axc_objects
.rbe_parent = (parent)->axo_axc_objects.rbe_parent)) { if (
(parent) == ((parent)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left) ((parent)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left = (tmp); else ((parent)->axo_axc_objects.rbe_parent
)->axo_axc_objects.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axo_axc_objects.rbe_right = (parent); (parent
)->axo_axc_objects.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axo_axc_objects.rbe_parent)) do {} while (0); } while
(0); tmp = (parent)->axo_axc_objects.rbe_left; } if (((tmp
)->axo_axc_objects.rbe_left == ((void *)0) || ((tmp)->axo_axc_objects
.rbe_left)->axo_axc_objects.rbe_color == 0) && ((tmp
)->axo_axc_objects.rbe_right == ((void *)0) || ((tmp)->
axo_axc_objects.rbe_right)->axo_axc_objects.rbe_color == 0
)) { (tmp)->axo_axc_objects.rbe_color = 1; elm = parent; parent
= (elm)->axo_axc_objects.rbe_parent; } else { if ((tmp)->
axo_axc_objects.rbe_left == ((void *)0) || ((tmp)->axo_axc_objects
.rbe_left)->axo_axc_objects.rbe_color == 0) { struct agentx_object
*oright; if ((oright = (tmp)->axo_axc_objects.rbe_right))
(oright)->axo_axc_objects.rbe_color = 0; (tmp)->axo_axc_objects
.rbe_color = 1; do { (oright) = (tmp)->axo_axc_objects.rbe_right
; if (((tmp)->axo_axc_objects.rbe_right = (oright)->axo_axc_objects
.rbe_left)) { ((oright)->axo_axc_objects.rbe_left)->axo_axc_objects
.rbe_parent = (tmp); } do {} while (0); if (((oright)->axo_axc_objects
.rbe_parent = (tmp)->axo_axc_objects.rbe_parent)) { if ((tmp
) == ((tmp)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left) ((tmp)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left = (oright); else ((tmp)->axo_axc_objects.rbe_parent
)->axo_axc_objects.rbe_right = (oright); } else (head)->
rbh_root = (oright); (oright)->axo_axc_objects.rbe_left = (
tmp); (tmp)->axo_axc_objects.rbe_parent = (oright); do {} while
(0); if (((oright)->axo_axc_objects.rbe_parent)) do {} while
(0); } while (0); tmp = (parent)->axo_axc_objects.rbe_left
; } (tmp)->axo_axc_objects.rbe_color = (parent)->axo_axc_objects
.rbe_color; (parent)->axo_axc_objects.rbe_color = 0; if ((
tmp)->axo_axc_objects.rbe_left) ((tmp)->axo_axc_objects
.rbe_left)->axo_axc_objects.rbe_color = 0; do { (tmp) = (parent
)->axo_axc_objects.rbe_left; if (((parent)->axo_axc_objects
.rbe_left = (tmp)->axo_axc_objects.rbe_right)) { ((tmp)->
axo_axc_objects.rbe_right)->axo_axc_objects.rbe_parent = (
parent); } do {} while (0); if (((tmp)->axo_axc_objects.rbe_parent
= (parent)->axo_axc_objects.rbe_parent)) { if ((parent) ==
((parent)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left) ((parent)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left = (tmp); else ((parent)->axo_axc_objects.rbe_parent
)->axo_axc_objects.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axo_axc_objects.rbe_right = (parent); (parent
)->axo_axc_objects.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axo_axc_objects.rbe_parent)) do {} while (0); } while
(0); elm = (head)->rbh_root; break; } } } if (elm) (elm)->
axo_axc_objects.rbe_color = 0; } __attribute__((__unused__)) static
struct agentx_object * axc_objects_RB_REMOVE(struct axc_objects
*head, struct agentx_object *elm) { struct agentx_object *child
, *parent, *old = elm; int color; if ((elm)->axo_axc_objects
.rbe_left == ((void *)0)) child = (elm)->axo_axc_objects.rbe_right
; else if ((elm)->axo_axc_objects.rbe_right == ((void *)0)
) child = (elm)->axo_axc_objects.rbe_left; else { struct agentx_object
*left; elm = (elm)->axo_axc_objects.rbe_right; while ((left
= (elm)->axo_axc_objects.rbe_left)) elm = left; child = (
elm)->axo_axc_objects.rbe_right; parent = (elm)->axo_axc_objects
.rbe_parent; color = (elm)->axo_axc_objects.rbe_color; if (
child) (child)->axo_axc_objects.rbe_parent = parent; if (parent
) { if ((parent)->axo_axc_objects.rbe_left == elm) (parent
)->axo_axc_objects.rbe_left = child; else (parent)->axo_axc_objects
.rbe_right = child; do {} while (0); } else (head)->rbh_root
= child; if ((elm)->axo_axc_objects.rbe_parent == old) parent
= elm; (elm)->axo_axc_objects = (old)->axo_axc_objects
; if ((old)->axo_axc_objects.rbe_parent) { if (((old)->
axo_axc_objects.rbe_parent)->axo_axc_objects.rbe_left == old
) ((old)->axo_axc_objects.rbe_parent)->axo_axc_objects.
rbe_left = elm; else ((old)->axo_axc_objects.rbe_parent)->
axo_axc_objects.rbe_right = elm; do {} while (0); } else (head
)->rbh_root = elm; ((old)->axo_axc_objects.rbe_left)->
axo_axc_objects.rbe_parent = elm; if ((old)->axo_axc_objects
.rbe_right) ((old)->axo_axc_objects.rbe_right)->axo_axc_objects
.rbe_parent = elm; if (parent) { left = parent; do { do {} while
(0); } while ((left = (left)->axo_axc_objects.rbe_parent)
); } goto color; } parent = (elm)->axo_axc_objects.rbe_parent
; color = (elm)->axo_axc_objects.rbe_color; if (child) (child
)->axo_axc_objects.rbe_parent = parent; if (parent) { if (
(parent)->axo_axc_objects.rbe_left == elm) (parent)->axo_axc_objects
.rbe_left = child; else (parent)->axo_axc_objects.rbe_right
= child; do {} while (0); } else (head)->rbh_root = child
; color: if (color == 0) axc_objects_RB_REMOVE_COLOR(head, parent
, child); return (old); } __attribute__((__unused__)) static struct
agentx_object * axc_objects_RB_INSERT(struct axc_objects *head
, struct agentx_object *elm) { struct agentx_object *tmp; struct
agentx_object *parent = ((void *)0); int comp = 0; tmp = (head
)->rbh_root; while (tmp) { parent = tmp; comp = (agentx_object_cmp
)(elm, parent); if (comp < 0) tmp = (tmp)->axo_axc_objects
.rbe_left; else if (comp > 0) tmp = (tmp)->axo_axc_objects
.rbe_right; else return (tmp); } do { (elm)->axo_axc_objects
.rbe_parent = parent; (elm)->axo_axc_objects.rbe_left = (elm
)->axo_axc_objects.rbe_right = ((void *)0); (elm)->axo_axc_objects
.rbe_color = 1; } while (0); if (parent != ((void *)0)) { if (
comp < 0) (parent)->axo_axc_objects.rbe_left = elm; else
(parent)->axo_axc_objects.rbe_right = elm; do {} while (0
); } else (head)->rbh_root = elm; axc_objects_RB_INSERT_COLOR
(head, elm); return (((void *)0)); } __attribute__((__unused__
)) static struct agentx_object * axc_objects_RB_FIND(struct axc_objects
*head, struct agentx_object *elm) { struct agentx_object *tmp
= (head)->rbh_root; int comp; while (tmp) { comp = agentx_object_cmp
(elm, tmp); if (comp < 0) tmp = (tmp)->axo_axc_objects.
rbe_left; else if (comp > 0) tmp = (tmp)->axo_axc_objects
.rbe_right; else return (tmp); } return (((void *)0)); } __attribute__
((__unused__)) static struct agentx_object * axc_objects_RB_NFIND
(struct axc_objects *head, struct agentx_object *elm) { struct
agentx_object *tmp = (head)->rbh_root; struct agentx_object
*res = ((void *)0); int comp; while (tmp) { comp = agentx_object_cmp
(elm, tmp); if (comp < 0) { res = tmp; tmp = (tmp)->axo_axc_objects
.rbe_left; } else if (comp > 0) tmp = (tmp)->axo_axc_objects
.rbe_right; else return (tmp); } return (res); } __attribute__
((__unused__)) static struct agentx_object * axc_objects_RB_NEXT
(struct agentx_object *elm) { if ((elm)->axo_axc_objects.rbe_right
) { elm = (elm)->axo_axc_objects.rbe_right; while ((elm)->
axo_axc_objects.rbe_left) elm = (elm)->axo_axc_objects.rbe_left
; } else { if ((elm)->axo_axc_objects.rbe_parent &&
(elm == ((elm)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left)) elm = (elm)->axo_axc_objects.rbe_parent; else {
while ((elm)->axo_axc_objects.rbe_parent && (elm ==
((elm)->axo_axc_objects.rbe_parent)->axo_axc_objects.rbe_right
)) elm = (elm)->axo_axc_objects.rbe_parent; elm = (elm)->
axo_axc_objects.rbe_parent; } } return (elm); } __attribute__
((__unused__)) static struct agentx_object * axc_objects_RB_PREV
(struct agentx_object *elm) { if ((elm)->axo_axc_objects.rbe_left
) { elm = (elm)->axo_axc_objects.rbe_left; while ((elm)->
axo_axc_objects.rbe_right) elm = (elm)->axo_axc_objects.rbe_right
; } else { if ((elm)->axo_axc_objects.rbe_parent &&
(elm == ((elm)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_right)) elm = (elm)->axo_axc_objects.rbe_parent; else
{ while ((elm)->axo_axc_objects.rbe_parent && (elm
== ((elm)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left)) elm = (elm)->axo_axc_objects.rbe_parent; elm =
(elm)->axo_axc_objects.rbe_parent; } } return (elm); } __attribute__
((__unused__)) static struct agentx_object * axc_objects_RB_MINMAX
(struct axc_objects *head, int val) { struct agentx_object *tmp
= (head)->rbh_root; struct agentx_object *parent = ((void
*)0); while (tmp) { parent = tmp; if (val < 0) tmp = (tmp
)->axo_axc_objects.rbe_left; else tmp = (tmp)->axo_axc_objects
.rbe_right; } return (parent); }
4145 agentx_object_cmp)__attribute__((__unused__)) static void axc_objects_RB_INSERT_COLOR
(struct axc_objects *head, struct agentx_object *elm) { struct
agentx_object *parent, *gparent, *tmp; while ((parent = (elm
)->axo_axc_objects.rbe_parent) && (parent)->axo_axc_objects
.rbe_color == 1) { gparent = (parent)->axo_axc_objects.rbe_parent
; if (parent == (gparent)->axo_axc_objects.rbe_left) { tmp
= (gparent)->axo_axc_objects.rbe_right; if (tmp &&
(tmp)->axo_axc_objects.rbe_color == 1) { (tmp)->axo_axc_objects
.rbe_color = 0; do { (parent)->axo_axc_objects.rbe_color =
0; (gparent)->axo_axc_objects.rbe_color = 1; } while (0);
elm = gparent; continue; } if ((parent)->axo_axc_objects.
rbe_right == elm) { do { (tmp) = (parent)->axo_axc_objects
.rbe_right; if (((parent)->axo_axc_objects.rbe_right = (tmp
)->axo_axc_objects.rbe_left)) { ((tmp)->axo_axc_objects
.rbe_left)->axo_axc_objects.rbe_parent = (parent); } do {}
while (0); if (((tmp)->axo_axc_objects.rbe_parent = (parent
)->axo_axc_objects.rbe_parent)) { if ((parent) == ((parent
)->axo_axc_objects.rbe_parent)->axo_axc_objects.rbe_left
) ((parent)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left = (tmp); else ((parent)->axo_axc_objects.rbe_parent
)->axo_axc_objects.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axo_axc_objects.rbe_left = (parent); (parent
)->axo_axc_objects.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axo_axc_objects.rbe_parent)) do {} while (0); } while
(0); tmp = parent; parent = elm; elm = tmp; } do { (parent)->
axo_axc_objects.rbe_color = 0; (gparent)->axo_axc_objects.
rbe_color = 1; } while (0); do { (tmp) = (gparent)->axo_axc_objects
.rbe_left; if (((gparent)->axo_axc_objects.rbe_left = (tmp
)->axo_axc_objects.rbe_right)) { ((tmp)->axo_axc_objects
.rbe_right)->axo_axc_objects.rbe_parent = (gparent); } do {
} while (0); if (((tmp)->axo_axc_objects.rbe_parent = (gparent
)->axo_axc_objects.rbe_parent)) { if ((gparent) == ((gparent
)->axo_axc_objects.rbe_parent)->axo_axc_objects.rbe_left
) ((gparent)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left = (tmp); else ((gparent)->axo_axc_objects.rbe_parent
)->axo_axc_objects.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axo_axc_objects.rbe_right = (gparent); (gparent
)->axo_axc_objects.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axo_axc_objects.rbe_parent)) do {} while (0); } while
(0); } else { tmp = (gparent)->axo_axc_objects.rbe_left; if
(tmp && (tmp)->axo_axc_objects.rbe_color == 1) { (
tmp)->axo_axc_objects.rbe_color = 0; do { (parent)->axo_axc_objects
.rbe_color = 0; (gparent)->axo_axc_objects.rbe_color = 1; }
while (0); elm = gparent; continue; } if ((parent)->axo_axc_objects
.rbe_left == elm) { do { (tmp) = (parent)->axo_axc_objects
.rbe_left; if (((parent)->axo_axc_objects.rbe_left = (tmp)
->axo_axc_objects.rbe_right)) { ((tmp)->axo_axc_objects
.rbe_right)->axo_axc_objects.rbe_parent = (parent); } do {
} while (0); if (((tmp)->axo_axc_objects.rbe_parent = (parent
)->axo_axc_objects.rbe_parent)) { if ((parent) == ((parent
)->axo_axc_objects.rbe_parent)->axo_axc_objects.rbe_left
) ((parent)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left = (tmp); else ((parent)->axo_axc_objects.rbe_parent
)->axo_axc_objects.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axo_axc_objects.rbe_right = (parent); (parent
)->axo_axc_objects.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axo_axc_objects.rbe_parent)) do {} while (0); } while
(0); tmp = parent; parent = elm; elm = tmp; } do { (parent)->
axo_axc_objects.rbe_color = 0; (gparent)->axo_axc_objects.
rbe_color = 1; } while (0); do { (tmp) = (gparent)->axo_axc_objects
.rbe_right; if (((gparent)->axo_axc_objects.rbe_right = (tmp
)->axo_axc_objects.rbe_left)) { ((tmp)->axo_axc_objects
.rbe_left)->axo_axc_objects.rbe_parent = (gparent); } do {
} while (0); if (((tmp)->axo_axc_objects.rbe_parent = (gparent
)->axo_axc_objects.rbe_parent)) { if ((gparent) == ((gparent
)->axo_axc_objects.rbe_parent)->axo_axc_objects.rbe_left
) ((gparent)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left = (tmp); else ((gparent)->axo_axc_objects.rbe_parent
)->axo_axc_objects.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axo_axc_objects.rbe_left = (gparent); (gparent
)->axo_axc_objects.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axo_axc_objects.rbe_parent)) do {} while (0); } while
(0); } } (head->rbh_root)->axo_axc_objects.rbe_color =
0; } __attribute__((__unused__)) static void axc_objects_RB_REMOVE_COLOR
(struct axc_objects *head, struct agentx_object *parent, struct
agentx_object *elm) { struct agentx_object *tmp; while ((elm
== ((void *)0) || (elm)->axo_axc_objects.rbe_color == 0) &&
elm != (head)->rbh_root) { if ((parent)->axo_axc_objects
.rbe_left == elm) { tmp = (parent)->axo_axc_objects.rbe_right
; if ((tmp)->axo_axc_objects.rbe_color == 1) { do { (tmp)->
axo_axc_objects.rbe_color = 0; (parent)->axo_axc_objects.rbe_color
= 1; } while (0); do { (tmp) = (parent)->axo_axc_objects.
rbe_right; if (((parent)->axo_axc_objects.rbe_right = (tmp
)->axo_axc_objects.rbe_left)) { ((tmp)->axo_axc_objects
.rbe_left)->axo_axc_objects.rbe_parent = (parent); } do {}
while (0); if (((tmp)->axo_axc_objects.rbe_parent = (parent
)->axo_axc_objects.rbe_parent)) { if ((parent) == ((parent
)->axo_axc_objects.rbe_parent)->axo_axc_objects.rbe_left
) ((parent)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left = (tmp); else ((parent)->axo_axc_objects.rbe_parent
)->axo_axc_objects.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axo_axc_objects.rbe_left = (parent); (parent
)->axo_axc_objects.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axo_axc_objects.rbe_parent)) do {} while (0); } while
(0); tmp = (parent)->axo_axc_objects.rbe_right; } if (((tmp
)->axo_axc_objects.rbe_left == ((void *)0) || ((tmp)->axo_axc_objects
.rbe_left)->axo_axc_objects.rbe_color == 0) && ((tmp
)->axo_axc_objects.rbe_right == ((void *)0) || ((tmp)->
axo_axc_objects.rbe_right)->axo_axc_objects.rbe_color == 0
)) { (tmp)->axo_axc_objects.rbe_color = 1; elm = parent; parent
= (elm)->axo_axc_objects.rbe_parent; } else { if ((tmp)->
axo_axc_objects.rbe_right == ((void *)0) || ((tmp)->axo_axc_objects
.rbe_right)->axo_axc_objects.rbe_color == 0) { struct agentx_object
*oleft; if ((oleft = (tmp)->axo_axc_objects.rbe_left)) (oleft
)->axo_axc_objects.rbe_color = 0; (tmp)->axo_axc_objects
.rbe_color = 1; do { (oleft) = (tmp)->axo_axc_objects.rbe_left
; if (((tmp)->axo_axc_objects.rbe_left = (oleft)->axo_axc_objects
.rbe_right)) { ((oleft)->axo_axc_objects.rbe_right)->axo_axc_objects
.rbe_parent = (tmp); } do {} while (0); if (((oleft)->axo_axc_objects
.rbe_parent = (tmp)->axo_axc_objects.rbe_parent)) { if ((tmp
) == ((tmp)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left) ((tmp)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left = (oleft); else ((tmp)->axo_axc_objects.rbe_parent
)->axo_axc_objects.rbe_right = (oleft); } else (head)->
rbh_root = (oleft); (oleft)->axo_axc_objects.rbe_right = (
tmp); (tmp)->axo_axc_objects.rbe_parent = (oleft); do {} while
(0); if (((oleft)->axo_axc_objects.rbe_parent)) do {} while
(0); } while (0); tmp = (parent)->axo_axc_objects.rbe_right
; } (tmp)->axo_axc_objects.rbe_color = (parent)->axo_axc_objects
.rbe_color; (parent)->axo_axc_objects.rbe_color = 0; if ((
tmp)->axo_axc_objects.rbe_right) ((tmp)->axo_axc_objects
.rbe_right)->axo_axc_objects.rbe_color = 0; do { (tmp) = (
parent)->axo_axc_objects.rbe_right; if (((parent)->axo_axc_objects
.rbe_right = (tmp)->axo_axc_objects.rbe_left)) { ((tmp)->
axo_axc_objects.rbe_left)->axo_axc_objects.rbe_parent = (parent
); } do {} while (0); if (((tmp)->axo_axc_objects.rbe_parent
= (parent)->axo_axc_objects.rbe_parent)) { if ((parent) ==
((parent)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left) ((parent)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left = (tmp); else ((parent)->axo_axc_objects.rbe_parent
)->axo_axc_objects.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axo_axc_objects.rbe_left = (parent); (parent
)->axo_axc_objects.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axo_axc_objects.rbe_parent)) do {} while (0); } while
(0); elm = (head)->rbh_root; break; } } else { tmp = (parent
)->axo_axc_objects.rbe_left; if ((tmp)->axo_axc_objects
.rbe_color == 1) { do { (tmp)->axo_axc_objects.rbe_color =
0; (parent)->axo_axc_objects.rbe_color = 1; } while (0); do
{ (tmp) = (parent)->axo_axc_objects.rbe_left; if (((parent
)->axo_axc_objects.rbe_left = (tmp)->axo_axc_objects.rbe_right
)) { ((tmp)->axo_axc_objects.rbe_right)->axo_axc_objects
.rbe_parent = (parent); } do {} while (0); if (((tmp)->axo_axc_objects
.rbe_parent = (parent)->axo_axc_objects.rbe_parent)) { if (
(parent) == ((parent)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left) ((parent)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left = (tmp); else ((parent)->axo_axc_objects.rbe_parent
)->axo_axc_objects.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axo_axc_objects.rbe_right = (parent); (parent
)->axo_axc_objects.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axo_axc_objects.rbe_parent)) do {} while (0); } while
(0); tmp = (parent)->axo_axc_objects.rbe_left; } if (((tmp
)->axo_axc_objects.rbe_left == ((void *)0) || ((tmp)->axo_axc_objects
.rbe_left)->axo_axc_objects.rbe_color == 0) && ((tmp
)->axo_axc_objects.rbe_right == ((void *)0) || ((tmp)->
axo_axc_objects.rbe_right)->axo_axc_objects.rbe_color == 0
)) { (tmp)->axo_axc_objects.rbe_color = 1; elm = parent; parent
= (elm)->axo_axc_objects.rbe_parent; } else { if ((tmp)->
axo_axc_objects.rbe_left == ((void *)0) || ((tmp)->axo_axc_objects
.rbe_left)->axo_axc_objects.rbe_color == 0) { struct agentx_object
*oright; if ((oright = (tmp)->axo_axc_objects.rbe_right))
(oright)->axo_axc_objects.rbe_color = 0; (tmp)->axo_axc_objects
.rbe_color = 1; do { (oright) = (tmp)->axo_axc_objects.rbe_right
; if (((tmp)->axo_axc_objects.rbe_right = (oright)->axo_axc_objects
.rbe_left)) { ((oright)->axo_axc_objects.rbe_left)->axo_axc_objects
.rbe_parent = (tmp); } do {} while (0); if (((oright)->axo_axc_objects
.rbe_parent = (tmp)->axo_axc_objects.rbe_parent)) { if ((tmp
) == ((tmp)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left) ((tmp)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left = (oright); else ((tmp)->axo_axc_objects.rbe_parent
)->axo_axc_objects.rbe_right = (oright); } else (head)->
rbh_root = (oright); (oright)->axo_axc_objects.rbe_left = (
tmp); (tmp)->axo_axc_objects.rbe_parent = (oright); do {} while
(0); if (((oright)->axo_axc_objects.rbe_parent)) do {} while
(0); } while (0); tmp = (parent)->axo_axc_objects.rbe_left
; } (tmp)->axo_axc_objects.rbe_color = (parent)->axo_axc_objects
.rbe_color; (parent)->axo_axc_objects.rbe_color = 0; if ((
tmp)->axo_axc_objects.rbe_left) ((tmp)->axo_axc_objects
.rbe_left)->axo_axc_objects.rbe_color = 0; do { (tmp) = (parent
)->axo_axc_objects.rbe_left; if (((parent)->axo_axc_objects
.rbe_left = (tmp)->axo_axc_objects.rbe_right)) { ((tmp)->
axo_axc_objects.rbe_right)->axo_axc_objects.rbe_parent = (
parent); } do {} while (0); if (((tmp)->axo_axc_objects.rbe_parent
= (parent)->axo_axc_objects.rbe_parent)) { if ((parent) ==
((parent)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left) ((parent)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left = (tmp); else ((parent)->axo_axc_objects.rbe_parent
)->axo_axc_objects.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->axo_axc_objects.rbe_right = (parent); (parent
)->axo_axc_objects.rbe_parent = (tmp); do {} while (0); if
(((tmp)->axo_axc_objects.rbe_parent)) do {} while (0); } while
(0); elm = (head)->rbh_root; break; } } } if (elm) (elm)->
axo_axc_objects.rbe_color = 0; } __attribute__((__unused__)) static
struct agentx_object * axc_objects_RB_REMOVE(struct axc_objects
*head, struct agentx_object *elm) { struct agentx_object *child
, *parent, *old = elm; int color; if ((elm)->axo_axc_objects
.rbe_left == ((void *)0)) child = (elm)->axo_axc_objects.rbe_right
; else if ((elm)->axo_axc_objects.rbe_right == ((void *)0)
) child = (elm)->axo_axc_objects.rbe_left; else { struct agentx_object
*left; elm = (elm)->axo_axc_objects.rbe_right; while ((left
= (elm)->axo_axc_objects.rbe_left)) elm = left; child = (
elm)->axo_axc_objects.rbe_right; parent = (elm)->axo_axc_objects
.rbe_parent; color = (elm)->axo_axc_objects.rbe_color; if (
child) (child)->axo_axc_objects.rbe_parent = parent; if (parent
) { if ((parent)->axo_axc_objects.rbe_left == elm) (parent
)->axo_axc_objects.rbe_left = child; else (parent)->axo_axc_objects
.rbe_right = child; do {} while (0); } else (head)->rbh_root
= child; if ((elm)->axo_axc_objects.rbe_parent == old) parent
= elm; (elm)->axo_axc_objects = (old)->axo_axc_objects
; if ((old)->axo_axc_objects.rbe_parent) { if (((old)->
axo_axc_objects.rbe_parent)->axo_axc_objects.rbe_left == old
) ((old)->axo_axc_objects.rbe_parent)->axo_axc_objects.
rbe_left = elm; else ((old)->axo_axc_objects.rbe_parent)->
axo_axc_objects.rbe_right = elm; do {} while (0); } else (head
)->rbh_root = elm; ((old)->axo_axc_objects.rbe_left)->
axo_axc_objects.rbe_parent = elm; if ((old)->axo_axc_objects
.rbe_right) ((old)->axo_axc_objects.rbe_right)->axo_axc_objects
.rbe_parent = elm; if (parent) { left = parent; do { do {} while
(0); } while ((left = (left)->axo_axc_objects.rbe_parent)
); } goto color; } parent = (elm)->axo_axc_objects.rbe_parent
; color = (elm)->axo_axc_objects.rbe_color; if (child) (child
)->axo_axc_objects.rbe_parent = parent; if (parent) { if (
(parent)->axo_axc_objects.rbe_left == elm) (parent)->axo_axc_objects
.rbe_left = child; else (parent)->axo_axc_objects.rbe_right
= child; do {} while (0); } else (head)->rbh_root = child
; color: if (color == 0) axc_objects_RB_REMOVE_COLOR(head, parent
, child); return (old); } __attribute__((__unused__)) static struct
agentx_object * axc_objects_RB_INSERT(struct axc_objects *head
, struct agentx_object *elm) { struct agentx_object *tmp; struct
agentx_object *parent = ((void *)0); int comp = 0; tmp = (head
)->rbh_root; while (tmp) { parent = tmp; comp = (agentx_object_cmp
)(elm, parent); if (comp < 0) tmp = (tmp)->axo_axc_objects
.rbe_left; else if (comp > 0) tmp = (tmp)->axo_axc_objects
.rbe_right; else return (tmp); } do { (elm)->axo_axc_objects
.rbe_parent = parent; (elm)->axo_axc_objects.rbe_left = (elm
)->axo_axc_objects.rbe_right = ((void *)0); (elm)->axo_axc_objects
.rbe_color = 1; } while (0); if (parent != ((void *)0)) { if (
comp < 0) (parent)->axo_axc_objects.rbe_left = elm; else
(parent)->axo_axc_objects.rbe_right = elm; do {} while (0
); } else (head)->rbh_root = elm; axc_objects_RB_INSERT_COLOR
(head, elm); return (((void *)0)); } __attribute__((__unused__
)) static struct agentx_object * axc_objects_RB_FIND(struct axc_objects
*head, struct agentx_object *elm) { struct agentx_object *tmp
= (head)->rbh_root; int comp; while (tmp) { comp = agentx_object_cmp
(elm, tmp); if (comp < 0) tmp = (tmp)->axo_axc_objects.
rbe_left; else if (comp > 0) tmp = (tmp)->axo_axc_objects
.rbe_right; else return (tmp); } return (((void *)0)); } __attribute__
((__unused__)) static struct agentx_object * axc_objects_RB_NFIND
(struct axc_objects *head, struct agentx_object *elm) { struct
agentx_object *tmp = (head)->rbh_root; struct agentx_object
*res = ((void *)0); int comp; while (tmp) { comp = agentx_object_cmp
(elm, tmp); if (comp < 0) { res = tmp; tmp = (tmp)->axo_axc_objects
.rbe_left; } else if (comp > 0) tmp = (tmp)->axo_axc_objects
.rbe_right; else return (tmp); } return (res); } __attribute__
((__unused__)) static struct agentx_object * axc_objects_RB_NEXT
(struct agentx_object *elm) { if ((elm)->axo_axc_objects.rbe_right
) { elm = (elm)->axo_axc_objects.rbe_right; while ((elm)->
axo_axc_objects.rbe_left) elm = (elm)->axo_axc_objects.rbe_left
; } else { if ((elm)->axo_axc_objects.rbe_parent &&
(elm == ((elm)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left)) elm = (elm)->axo_axc_objects.rbe_parent; else {
while ((elm)->axo_axc_objects.rbe_parent && (elm ==
((elm)->axo_axc_objects.rbe_parent)->axo_axc_objects.rbe_right
)) elm = (elm)->axo_axc_objects.rbe_parent; elm = (elm)->
axo_axc_objects.rbe_parent; } } return (elm); } __attribute__
((__unused__)) static struct agentx_object * axc_objects_RB_PREV
(struct agentx_object *elm) { if ((elm)->axo_axc_objects.rbe_left
) { elm = (elm)->axo_axc_objects.rbe_left; while ((elm)->
axo_axc_objects.rbe_right) elm = (elm)->axo_axc_objects.rbe_right
; } else { if ((elm)->axo_axc_objects.rbe_parent &&
(elm == ((elm)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_right)) elm = (elm)->axo_axc_objects.rbe_parent; else
{ while ((elm)->axo_axc_objects.rbe_parent && (elm
== ((elm)->axo_axc_objects.rbe_parent)->axo_axc_objects
.rbe_left)) elm = (elm)->axo_axc_objects.rbe_parent; elm =
(elm)->axo_axc_objects.rbe_parent; } } return (elm); } __attribute__
((__unused__)) static struct agentx_object * axc_objects_RB_MINMAX
(struct axc_objects *head, int val) { struct agentx_object *tmp
= (head)->rbh_root; struct agentx_object *parent = ((void
*)0); while (tmp) { parent = tmp; if (val < 0) tmp = (tmp
)->axo_axc_objects.rbe_left; else tmp = (tmp)->axo_axc_objects
.rbe_right; } return (parent); }