Bug Summary

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