Bug Summary

File:src/usr.sbin/snmpd/application.c
Warning:line 1248, column 7
Access to field 'be_class' results in a dereference of a null pointer (loaded from variable 'value')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name application.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/snmpd/obj -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/usr.sbin/snmpd -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/snmpd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.sbin/snmpd/application.c
1/* $OpenBSD: application.c,v 1.41 2023/12/21 12:43:30 martijn Exp $ */
2
3/*
4 * Copyright (c) 2021 Martijn van Duren <martijn@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/queue.h>
20#include <sys/time.h>
21#include <sys/tree.h>
22#include <sys/types.h>
23
24#include <assert.h>
25#include <errno(*__errno()).h>
26#include <event.h>
27#include <inttypes.h>
28#include <stdlib.h>
29#include <stdio.h>
30#include <string.h>
31
32#include "application.h"
33#include "log.h"
34#include "smi.h"
35#include "snmp.h"
36#include "snmpe.h"
37#include "mib.h"
38
39#define OID(...)(struct ber_oid){ { ... }, (sizeof((uint32_t []) { ... }) / sizeof
(uint32_t)) }
(struct ber_oid){ { __VA_ARGS__ }, \
40 (sizeof((uint32_t []) { __VA_ARGS__ }) / sizeof(uint32_t)) }
41
42TAILQ_HEAD(, appl_context)struct { struct appl_context *tqh_first; struct appl_context *
*tqh_last; }
contexts = TAILQ_HEAD_INITIALIZER(contexts){ ((void *)0), &(contexts).tqh_first };
43
44struct appl_agentcap {
45 struct appl_backend *aa_backend;
46 struct appl_context *aa_context;
47 uint32_t aa_index;
48 struct ber_oid aa_oid;
49 char aa_descr[256];
50 int aa_uptime;
51
52 TAILQ_ENTRY(appl_agentcap)struct { struct appl_agentcap *tqe_next; struct appl_agentcap
**tqe_prev; }
aa_entry;
53};
54
55struct appl_context {
56 char ac_name[APPL_CONTEXTNAME_MAX32 + 1];
57
58 RB_HEAD(appl_regions, appl_region)struct appl_regions { struct appl_region *rbh_root; } ac_regions;
59 TAILQ_HEAD(, appl_agentcap)struct { struct appl_agentcap *tqh_first; struct appl_agentcap
**tqh_last; }
ac_agentcaps;
60 int ac_agentcap_lastid;
61 int ac_agentcap_lastchange;
62
63 TAILQ_ENTRY(appl_context)struct { struct appl_context *tqe_next; struct appl_context *
*tqe_prev; }
ac_entries;
64};
65
66struct appl_region {
67 struct ber_oid ar_oid;
68 uint8_t ar_priority;
69 int32_t ar_timeout;
70 int ar_instance;
71 int ar_subtree; /* Claim entire subtree */
72 struct appl_backend *ar_backend;
73 struct appl_region *ar_next; /* Sorted by priority */
74
75 RB_ENTRY(appl_region)struct { struct appl_region *rbe_left; struct appl_region *rbe_right
; struct appl_region *rbe_parent; int rbe_color; }
ar_entry;
76};
77
78struct appl_request_upstream {
79 struct appl_context *aru_ctx;
80 struct snmp_message *aru_statereference;
81 enum snmp_pdutype aru_requesttype;
82 enum snmp_pdutype aru_responsetype;
83 int32_t aru_requestid; /* upstream requestid */
84 int32_t aru_transactionid; /* RFC 2741 section 6.1 */
85 uint16_t aru_nonrepeaters;
86 uint16_t aru_maxrepetitions;
87 struct appl_varbind_internal *aru_vblist;
88 size_t aru_varbindlen;
89 enum appl_error aru_error;
90 int16_t aru_index;
91 int aru_locked; /* Prevent recursion through appl_request_send */
92
93 enum snmp_version aru_pduversion;
94};
95
96struct appl_request_downstream {
97 struct appl_request_upstream *ard_request;
98 struct appl_backend *ard_backend;
99 enum snmp_pdutype ard_requesttype;
100 uint16_t ard_nonrepeaters;
101 uint16_t ard_maxrepetitions;
102 int32_t ard_requestid;
103 uint8_t ard_retries;
104
105 struct appl_varbind_internal *ard_vblist;
106 struct event ard_timer;
107
108 RB_ENTRY(appl_request_downstream)struct { struct appl_request_downstream *rbe_left; struct appl_request_downstream
*rbe_right; struct appl_request_downstream *rbe_parent; int rbe_color
; }
ard_entry;
109};
110
111enum appl_varbind_state {
112 APPL_VBSTATE_MUSTFILL,
113 APPL_VBSTATE_NEW,
114 APPL_VBSTATE_PENDING,
115 APPL_VBSTATE_DONE
116};
117
118struct appl_varbind_internal {
119 enum appl_varbind_state avi_state;
120 struct appl_varbind avi_varbind;
121 struct appl_region *avi_region;
122 struct ber_oid avi_origid;
123 int16_t avi_index;
124 struct appl_request_upstream *avi_request_upstream;
125 struct appl_request_downstream *avi_request_downstream;
126 struct appl_varbind_internal *avi_next;
127 struct appl_varbind_internal *avi_sub;
128};
129
130/* SNMP-TARGET-MIB (RFC 3413) */
131struct snmp_target_mib {
132 uint32_t snmp_unavailablecontexts;
133 uint32_t snmp_unknowncontexts;
134} snmp_target_mib;
135
136void appl_agentcap_free(struct appl_agentcap *);
137enum appl_error appl_region(struct appl_context *, uint32_t, uint8_t,
138 struct ber_oid *, int, int, struct appl_backend *);
139void appl_region_free(struct appl_context *, struct appl_region *);
140enum appl_error appl_region_unregister_match(struct appl_context *, uint8_t,
141 struct ber_oid *, char *, struct appl_backend *, int);
142struct appl_region *appl_region_find(struct appl_context *,
143 const struct ber_oid *);
144struct appl_region *appl_region_next(struct appl_context *,
145 struct ber_oid *, struct appl_region *);
146void appl_request_upstream_free(struct appl_request_upstream *);
147void appl_request_downstream_free(struct appl_request_downstream *);
148void appl_request_upstream_resolve(struct appl_request_upstream *);
149void appl_request_downstream_send(struct appl_request_downstream *);
150void appl_request_downstream_timeout(int, short, void *);
151void appl_request_upstream_reply(struct appl_request_upstream *);
152int appl_varbind_valid(struct appl_varbind *, struct appl_varbind_internal *,
153 int, int, int, const char **);
154int appl_error_valid(enum appl_error, enum snmp_pdutype);
155int appl_varbind_backend(struct appl_varbind_internal *);
156void appl_varbind_error(struct appl_varbind_internal *, enum appl_error);
157void appl_pdu_log(struct appl_backend *, enum snmp_pdutype, int32_t, uint16_t,
158 uint16_t, struct appl_varbind *);
159void ober_oid_nextsibling(struct ber_oid *);
160
161int appl_region_cmp(struct appl_region *, struct appl_region *);
162int appl_request_cmp(struct appl_request_downstream *,
163 struct appl_request_downstream *);
164
165RB_PROTOTYPE_STATIC(appl_regions, appl_region, ar_entry, appl_region_cmp)__attribute__((__unused__)) static void appl_regions_RB_INSERT_COLOR
(struct appl_regions *, struct appl_region *); __attribute__(
(__unused__)) static void appl_regions_RB_REMOVE_COLOR(struct
appl_regions *, struct appl_region *, struct appl_region *);
__attribute__((__unused__)) static struct appl_region *appl_regions_RB_REMOVE
(struct appl_regions *, struct appl_region *); __attribute__(
(__unused__)) static struct appl_region *appl_regions_RB_INSERT
(struct appl_regions *, struct appl_region *); __attribute__(
(__unused__)) static struct appl_region *appl_regions_RB_FIND
(struct appl_regions *, struct appl_region *); __attribute__(
(__unused__)) static struct appl_region *appl_regions_RB_NFIND
(struct appl_regions *, struct appl_region *); __attribute__(
(__unused__)) static struct appl_region *appl_regions_RB_NEXT
(struct appl_region *); __attribute__((__unused__)) static struct
appl_region *appl_regions_RB_PREV(struct appl_region *); __attribute__
((__unused__)) static struct appl_region *appl_regions_RB_MINMAX
(struct appl_regions *, int);
;
166RB_PROTOTYPE_STATIC(appl_requests, appl_request_downstream, ard_entry,__attribute__((__unused__)) static void appl_requests_RB_INSERT_COLOR
(struct appl_requests *, struct appl_request_downstream *); __attribute__
((__unused__)) static void appl_requests_RB_REMOVE_COLOR(struct
appl_requests *, struct appl_request_downstream *, struct appl_request_downstream
*);__attribute__((__unused__)) static struct appl_request_downstream
*appl_requests_RB_REMOVE(struct appl_requests *, struct appl_request_downstream
*); __attribute__((__unused__)) static struct appl_request_downstream
*appl_requests_RB_INSERT(struct appl_requests *, struct appl_request_downstream
*); __attribute__((__unused__)) static struct appl_request_downstream
*appl_requests_RB_FIND(struct appl_requests *, struct appl_request_downstream
*); __attribute__((__unused__)) static struct appl_request_downstream
*appl_requests_RB_NFIND(struct appl_requests *, struct appl_request_downstream
*); __attribute__((__unused__)) static struct appl_request_downstream
*appl_requests_RB_NEXT(struct appl_request_downstream *); __attribute__
((__unused__)) static struct appl_request_downstream *appl_requests_RB_PREV
(struct appl_request_downstream *); __attribute__((__unused__
)) static struct appl_request_downstream *appl_requests_RB_MINMAX
(struct appl_requests *, int);
167 appl_request_cmp)__attribute__((__unused__)) static void appl_requests_RB_INSERT_COLOR
(struct appl_requests *, struct appl_request_downstream *); __attribute__
((__unused__)) static void appl_requests_RB_REMOVE_COLOR(struct
appl_requests *, struct appl_request_downstream *, struct appl_request_downstream
*);__attribute__((__unused__)) static struct appl_request_downstream
*appl_requests_RB_REMOVE(struct appl_requests *, struct appl_request_downstream
*); __attribute__((__unused__)) static struct appl_request_downstream
*appl_requests_RB_INSERT(struct appl_requests *, struct appl_request_downstream
*); __attribute__((__unused__)) static struct appl_request_downstream
*appl_requests_RB_FIND(struct appl_requests *, struct appl_request_downstream
*); __attribute__((__unused__)) static struct appl_request_downstream
*appl_requests_RB_NFIND(struct appl_requests *, struct appl_request_downstream
*); __attribute__((__unused__)) static struct appl_request_downstream
*appl_requests_RB_NEXT(struct appl_request_downstream *); __attribute__
((__unused__)) static struct appl_request_downstream *appl_requests_RB_PREV
(struct appl_request_downstream *); __attribute__((__unused__
)) static struct appl_request_downstream *appl_requests_RB_MINMAX
(struct appl_requests *, int);
;
168
169#define APPL_CONTEXT_NAME(ctx)(ctx->ac_name[0] == '\0' ? ((void *)0) : ctx->ac_name) (ctx->ac_name[0] == '\0' ? NULL((void *)0) : ctx->ac_name)
170
171void
172appl(void)
173{
174 appl_agentx();
175}
176
177void
178appl_init(void)
179{
180 appl_blocklist_init();
181 appl_internal_init();
182 appl_agentx_init();
183}
184
185void
186appl_shutdown(void)
187{
188 struct appl_context *ctx, *tctx;
189
190 appl_blocklist_shutdown();
191 appl_internal_shutdown();
192 appl_agentx_shutdown();
193
194 TAILQ_FOREACH_SAFE(ctx, &contexts, ac_entries, tctx)for ((ctx) = ((&contexts)->tqh_first); (ctx) != ((void
*)0) && ((tctx) = ((ctx)->ac_entries.tqe_next), 1
); (ctx) = (tctx))
{
195 assert(RB_EMPTY(&(ctx->ac_regions)))((((&(ctx->ac_regions))->rbh_root == ((void *)0))) ?
(void)0 : __assert2("/usr/src/usr.sbin/snmpd/application.c",
195, __func__, "RB_EMPTY(&(ctx->ac_regions))"))
;
196 assert(TAILQ_EMPTY(&(ctx->ac_agentcaps)))(((((&(ctx->ac_agentcaps))->tqh_first) == ((void *)
0))) ? (void)0 : __assert2("/usr/src/usr.sbin/snmpd/application.c"
, 196, __func__, "TAILQ_EMPTY(&(ctx->ac_agentcaps))"))
;
197 TAILQ_REMOVE(&contexts, ctx, ac_entries)do { if (((ctx)->ac_entries.tqe_next) != ((void *)0)) (ctx
)->ac_entries.tqe_next->ac_entries.tqe_prev = (ctx)->
ac_entries.tqe_prev; else (&contexts)->tqh_last = (ctx
)->ac_entries.tqe_prev; *(ctx)->ac_entries.tqe_prev = (
ctx)->ac_entries.tqe_next; ; ; } while (0)
;
198 free(ctx);
199 }
200}
201
202struct appl_context *
203appl_context(const char *name, int create)
204{
205 struct appl_context *ctx;
206
207 if (name == NULL((void *)0))
208 name = "";
209
210 if (strlen(name) > APPL_CONTEXTNAME_MAX32) {
211 errno(*__errno()) = EINVAL22;
212 return NULL((void *)0);
213 }
214
215 TAILQ_FOREACH(ctx, &contexts, ac_entries)for((ctx) = ((&contexts)->tqh_first); (ctx) != ((void *
)0); (ctx) = ((ctx)->ac_entries.tqe_next))
{
216 if (strcmp(name, ctx->ac_name) == 0)
217 return ctx;
218 }
219
220 /* Always allow the default namespace */
221 if (!create && name[0] != '\0') {
222 errno(*__errno()) = ENOENT2;
223 return NULL((void *)0);
224 }
225
226 if ((ctx = malloc(sizeof(*ctx))) == NULL((void *)0))
227 return NULL((void *)0);
228
229 strlcpy(ctx->ac_name, name, sizeof(ctx->ac_name));
230 RB_INIT(&(ctx->ac_regions))do { (&(ctx->ac_regions))->rbh_root = ((void *)0); }
while (0)
;
231 TAILQ_INIT(&(ctx->ac_agentcaps))do { (&(ctx->ac_agentcaps))->tqh_first = ((void *)0
); (&(ctx->ac_agentcaps))->tqh_last = &(&(ctx
->ac_agentcaps))->tqh_first; } while (0)
;
232 ctx->ac_agentcap_lastid = 0;
233 ctx->ac_agentcap_lastchange = 0;
234
235 TAILQ_INSERT_TAIL(&contexts, ctx, ac_entries)do { (ctx)->ac_entries.tqe_next = ((void *)0); (ctx)->ac_entries
.tqe_prev = (&contexts)->tqh_last; *(&contexts)->
tqh_last = (ctx); (&contexts)->tqh_last = &(ctx)->
ac_entries.tqe_next; } while (0)
;
236 return ctx;
237}
238
239/* Name from RFC 2741 section 6.2.14 */
240enum appl_error
241appl_addagentcaps(const char *ctxname, struct ber_oid *oid, const char *descr,
242 struct appl_backend *backend)
243{
244 struct appl_context *ctx;
245 struct appl_agentcap *cap;
246 char oidbuf[1024];
247
248 if (ctxname == NULL((void *)0))
249 ctxname = "";
250
251 (void)smi_oid2string(oid, oidbuf, sizeof(oidbuf), 0);
252 log_info("%s: Adding agent capabilities %s context(%s)",
253 backend->ab_name, oidbuf, ctxname);
254
255 if ((ctx = appl_context(ctxname, 0)) == NULL((void *)0)) {
256 log_info("%s: Can't add agent capabilities %s: "
257 "Unsupported context \"%s\"", backend->ab_name, oidbuf,
258 ctxname);
259 return APPL_ERROR_UNSUPPORTEDCONTEXT;
260 }
261
262 if ((cap = malloc(sizeof(*cap))) == NULL((void *)0)) {
263 log_warn("%s: Can't add agent capabilities %s",
264 backend->ab_name, oidbuf);
265 return APPL_ERROR_PROCESSINGERROR;
266 }
267
268 cap->aa_backend = backend;
269 cap->aa_context = ctx;
270 cap->aa_index = ++ctx->ac_agentcap_lastid;
271 cap->aa_oid = *oid;
272 cap->aa_uptime = smi_getticks();
273 if (strlcpy(cap->aa_descr, descr,
274 sizeof(cap->aa_descr)) >= sizeof(cap->aa_descr)) {
275 log_info("%s: Can't add agent capabilities %s: "
276 "Invalid description", backend->ab_name, oidbuf);
277 free(cap);
278 return APPL_ERROR_PARSEERROR;
279 }
280
281 TAILQ_INSERT_TAIL(&(ctx->ac_agentcaps), cap, aa_entry)do { (cap)->aa_entry.tqe_next = ((void *)0); (cap)->aa_entry
.tqe_prev = (&(ctx->ac_agentcaps))->tqh_last; *(&
(ctx->ac_agentcaps))->tqh_last = (cap); (&(ctx->
ac_agentcaps))->tqh_last = &(cap)->aa_entry.tqe_next
; } while (0)
;
282 ctx->ac_agentcap_lastchange = cap->aa_uptime;
283
284 return APPL_ERROR_NOERROR;
285}
286
287/* Name from RFC2741 section 6.2.15 */
288enum appl_error
289appl_removeagentcaps(const char *ctxname, struct ber_oid *oid,
290 struct appl_backend *backend)
291{
292 struct appl_context *ctx;
293 struct appl_agentcap *cap, *tmp;
294 char oidbuf[1024];
295 int found = 0;
296
297 if (ctxname == NULL((void *)0))
298 ctxname = "";
299
300 (void)smi_oid2string(oid, oidbuf, sizeof(oidbuf), 0);
301 log_info("%s: Removing agent capabilities %s context(%s)",
302 backend->ab_name, oidbuf, ctxname);
303
304 if ((ctx = appl_context(ctxname, 0)) == NULL((void *)0)) {
305 log_info("%s: Can't remove agent capabilities %s: "
306 "Unsupported context \"%s\"", backend->ab_name, oidbuf,
307 ctxname);
308 return APPL_ERROR_UNSUPPORTEDCONTEXT;
309 }
310
311 TAILQ_FOREACH_SAFE(cap, &(ctx->ac_agentcaps), aa_entry, tmp)for ((cap) = ((&(ctx->ac_agentcaps))->tqh_first); (
cap) != ((void *)0) && ((tmp) = ((cap)->aa_entry.tqe_next
), 1); (cap) = (tmp))
{
312 /* No duplicate oid check, just continue */
313 if (cap->aa_backend != backend ||
314 ober_oid_cmp(oid, &(cap->aa_oid)) != 0)
315 continue;
316 found = 1;
317 appl_agentcap_free(cap);
318 }
319
320 if (found)
321 return APPL_ERROR_NOERROR;
322
323 log_info("%s: Can't remove agent capabilities %s: not found",
324 backend->ab_name, oidbuf);
325 return APPL_ERROR_UNKNOWNAGENTCAPS;
326}
327
328void
329appl_agentcap_free(struct appl_agentcap *cap)
330{
331 TAILQ_REMOVE(&(cap->aa_context->ac_agentcaps), cap, aa_entry)do { if (((cap)->aa_entry.tqe_next) != ((void *)0)) (cap)->
aa_entry.tqe_next->aa_entry.tqe_prev = (cap)->aa_entry.
tqe_prev; else (&(cap->aa_context->ac_agentcaps))->
tqh_last = (cap)->aa_entry.tqe_prev; *(cap)->aa_entry.tqe_prev
= (cap)->aa_entry.tqe_next; ; ; } while (0)
;
332 cap->aa_context->ac_agentcap_lastchange = smi_getticks();
333 free(cap);
334}
335
336struct ber_element *
337appl_sysorlastchange(struct ber_oid *oid)
338{
339 struct appl_context *ctx;
340 struct ber_element *value;
341
342 ctx = appl_context(NULL((void *)0), 0);
343 value = ober_add_integer(NULL((void *)0), ctx->ac_agentcap_lastchange);
344 if (value != NULL((void *)0))
345 ober_set_header(value, BER_CLASS_APPLICATION0x1, SNMP_T_TIMETICKS);
346 else
347 log_warn("ober_add_integer");
348
349 return value;
350}
351
352#define SYSORIDX_POS10 10
353struct ber_element *
354appl_sysortable(struct ber_oid *oid)
355{
356 struct appl_context *ctx;
357 struct appl_agentcap *cap;
358 struct ber_element *value = NULL((void *)0);
359
360 if (oid->bo_n != SYSORIDX_POS10 + 1)
361 goto notfound;
362
363 ctx = appl_context(NULL((void *)0), 0);
364 TAILQ_FOREACH(cap, &(ctx->ac_agentcaps), aa_entry)for((cap) = ((&(ctx->ac_agentcaps))->tqh_first); (cap
) != ((void *)0); (cap) = ((cap)->aa_entry.tqe_next))
{
365 if (cap->aa_index == oid->bo_id[SYSORIDX_POS10])
366 break;
367 }
368 if (cap == NULL((void *)0))
369 goto notfound;
370
371 if (ober_oid_cmp(&OID(MIB_sysORID)(struct ber_oid){ { 1, 3, 6, 1, 2, 1, 1, 9, 1, 2 }, (sizeof((
uint32_t []) { 1, 3, 6, 1, 2, 1, 1, 9, 1, 2 }) / sizeof(uint32_t
)) }
, oid) == -2)
372 value = ober_add_oid(NULL((void *)0), &(cap->aa_oid));
373 else if (ober_oid_cmp(&OID(MIB_sysORDescr)(struct ber_oid){ { 1, 3, 6, 1, 2, 1, 1, 9, 1, 3 }, (sizeof((
uint32_t []) { 1, 3, 6, 1, 2, 1, 1, 9, 1, 3 }) / sizeof(uint32_t
)) }
, oid) == -2)
374 value = ober_add_string(NULL((void *)0), cap->aa_descr);
375 else if (ober_oid_cmp(&OID(MIB_sysORUpTime)(struct ber_oid){ { 1, 3, 6, 1, 2, 1, 1, 9, 1, 4 }, (sizeof((
uint32_t []) { 1, 3, 6, 1, 2, 1, 1, 9, 1, 4 }) / sizeof(uint32_t
)) }
, oid) == -2) {
376 if ((value = ober_add_integer(NULL((void *)0), cap->aa_uptime)) != NULL((void *)0))
377 ober_set_header(value,
378 BER_CLASS_APPLICATION0x1, SNMP_T_TIMETICKS);
379 }
380 if (value == NULL((void *)0))
381 log_warn("ober_add_*");
382 return value;
383
384 notfound:
385 if ((value = appl_exception(APPL_EXC_NOSUCHINSTANCE)) == NULL((void *)0))
386 log_warn("appl_exception");
387 return value;
388}
389
390struct ber_element *
391appl_sysortable_getnext(int8_t include, struct ber_oid *oid)
392{
393 struct appl_context *ctx;
394 struct appl_agentcap *cap;
395 struct ber_element *value = NULL((void *)0);
396
397 if (oid->bo_n < SYSORIDX_POS10 + 1) {
398 include = 1;
399 oid->bo_id[SYSORIDX_POS10] = 0;
400 } else if (oid->bo_n < SYSORIDX_POS10 + 1)
401 include = 0;
402
403 ctx = appl_context(NULL((void *)0), 0);
404 TAILQ_FOREACH(cap, &(ctx->ac_agentcaps), aa_entry)for((cap) = ((&(ctx->ac_agentcaps))->tqh_first); (cap
) != ((void *)0); (cap) = ((cap)->aa_entry.tqe_next))
{
405 if (cap->aa_index > oid->bo_id[SYSORIDX_POS10])
406 break;
407 if (cap->aa_index == oid->bo_id[SYSORIDX_POS10] && include)
408 break;
409 }
410 if (cap == NULL((void *)0)) {
411 value = appl_exception(APPL_EXC_NOSUCHINSTANCE);
412 goto done;
413 }
414
415 oid->bo_id[SYSORIDX_POS10] = cap->aa_index;
416 oid->bo_n = SYSORIDX_POS10 + 1;
417
418 if (ober_oid_cmp(&OID(MIB_sysORID)(struct ber_oid){ { 1, 3, 6, 1, 2, 1, 1, 9, 1, 2 }, (sizeof((
uint32_t []) { 1, 3, 6, 1, 2, 1, 1, 9, 1, 2 }) / sizeof(uint32_t
)) }
, oid) == -2)
419 value = ober_add_oid(NULL((void *)0), &(cap->aa_oid));
420 else if (ober_oid_cmp(&OID(MIB_sysORDescr)(struct ber_oid){ { 1, 3, 6, 1, 2, 1, 1, 9, 1, 3 }, (sizeof((
uint32_t []) { 1, 3, 6, 1, 2, 1, 1, 9, 1, 3 }) / sizeof(uint32_t
)) }
, oid) == -2)
421 value = ober_add_string(NULL((void *)0), cap->aa_descr);
422 else if (ober_oid_cmp(&OID(MIB_sysORUpTime)(struct ber_oid){ { 1, 3, 6, 1, 2, 1, 1, 9, 1, 4 }, (sizeof((
uint32_t []) { 1, 3, 6, 1, 2, 1, 1, 9, 1, 4 }) / sizeof(uint32_t
)) }
, oid) == -2) {
423 if ((value = ober_add_integer(NULL((void *)0), cap->aa_uptime)) != NULL((void *)0))
424 ober_set_header(value,
425 BER_CLASS_APPLICATION0x1, SNMP_T_TIMETICKS);
426 }
427 done:
428 if (value == NULL((void *)0))
429 log_warn("ober_add_*");
430 return value;
431}
432
433struct ber_element *
434appl_targetmib(struct ber_oid *oid)
435{
436 struct ber_element *value = NULL((void *)0);
437
438 if (ober_oid_cmp(oid, &OID(MIB_snmpUnavailableContexts, 0)(struct ber_oid){ { 1, 3, 6, 1, 6, 3, 12, 1, 4, 0 }, (sizeof(
(uint32_t []) { 1, 3, 6, 1, 6, 3, 12, 1, 4, 0 }) / sizeof(uint32_t
)) }
) == 0)
439 value = ober_add_integer(NULL((void *)0),
440 snmp_target_mib.snmp_unavailablecontexts);
441 else if (ober_oid_cmp(oid, &OID(MIB_snmpUnknownContexts, 0)(struct ber_oid){ { 1, 3, 6, 1, 6, 3, 12, 1, 5, 0 }, (sizeof(
(uint32_t []) { 1, 3, 6, 1, 6, 3, 12, 1, 5, 0 }) / sizeof(uint32_t
)) }
) == 0)
442 value = ober_add_integer(NULL((void *)0),
443 snmp_target_mib.snmp_unknowncontexts);
444
445 if (value != NULL((void *)0))
446 ober_set_header(value, BER_CLASS_APPLICATION0x1, SNMP_T_COUNTER32);
447 return value;
448}
449
450enum appl_error
451appl_region(struct appl_context *ctx, uint32_t timeout, uint8_t priority,
452 struct ber_oid *oid, int instance, int subtree,
453 struct appl_backend *backend)
454{
455 struct appl_region *region = NULL((void *)0), *nregion;
456 char oidbuf[1024], regionbuf[1024], subidbuf[11];
457 size_t i;
458
459 /* Don't use smi_oid2string, because appl_register can't use it */
460 oidbuf[0] = '\0';
461 for (i = 0; i < oid->bo_n; i++) {
462 if (i != 0)
463 strlcat(oidbuf, ".", sizeof(oidbuf));
464 snprintf(subidbuf, sizeof(subidbuf), "%"PRIu32"u",
465 oid->bo_id[i]);
466 strlcat(oidbuf, subidbuf, sizeof(oidbuf));
467 }
468
469 /*
470 * Don't allow overlap when subtree flag is set.
471 * This allows us to keep control of certain regions like system.
472 */
473 region = appl_region_find(ctx, oid);
474 if (region != NULL((void *)0) && region->ar_subtree &&
475 region->ar_backend != backend)
476 goto overlap;
477
478 if ((nregion = malloc(sizeof(*nregion))) == NULL((void *)0)) {
479 log_warn("%s: Can't register %s: Processing error",
480 backend->ab_name, oidbuf);
481 return APPL_ERROR_PROCESSINGERROR;
482 }
483 nregion->ar_oid = *oid;
484 nregion->ar_priority = priority;
485 nregion->ar_timeout = timeout;
486 nregion->ar_instance = instance;
487 nregion->ar_subtree = subtree;
488 nregion->ar_backend = backend;
489 nregion->ar_next = NULL((void *)0);
490
491 region = RB_INSERT(appl_regions, &(ctx->ac_regions), nregion)appl_regions_RB_INSERT(&(ctx->ac_regions), nregion);
492 if (region == NULL((void *)0))
493 return APPL_ERROR_NOERROR;
494
495 if (region->ar_priority == priority)
496 goto duplicate;
497 if (region->ar_priority > priority) {
498 RB_REMOVE(appl_regions, &(ctx->ac_regions), region)appl_regions_RB_REMOVE(&(ctx->ac_regions), region);
499 RB_INSERT(appl_regions, &(ctx->ac_regions), nregion)appl_regions_RB_INSERT(&(ctx->ac_regions), nregion);
500 nregion->ar_next = region;
501 return APPL_ERROR_NOERROR;
502 }
503
504 while (region->ar_next != NULL((void *)0) &&
505 region->ar_next->ar_priority < priority)
506 region = region->ar_next;
507 if (region->ar_next != NULL((void *)0) && region->ar_next->ar_priority == priority)
508 goto duplicate;
509 nregion->ar_next = region->ar_next;
510 region->ar_next = nregion;
511
512 return APPL_ERROR_NOERROR;
513 duplicate:
514 free(nregion);
515 log_info("%s: %s priority %"PRId8"d"": Duplicate registration",
516 backend->ab_name, oidbuf, priority);
517 return APPL_ERROR_DUPLICATEREGISTRATION;
518 overlap:
519 regionbuf[0] = '\0';
520 for (i = 0; i < region->ar_oid.bo_n; i++) {
521 if (i != 0)
522 strlcat(regionbuf, ".", sizeof(regionbuf));
523 snprintf(subidbuf, sizeof(subidbuf), "%"PRIu32"u",
524 region->ar_oid.bo_id[i]);
525 strlcat(regionbuf, subidbuf, sizeof(regionbuf));
526 }
527 log_info("%s: %s overlaps with %s: Request denied",
528 backend->ab_name, oidbuf, regionbuf);
529 return APPL_ERROR_REQUESTDENIED;
530}
531
532/* Name from RFC 2741 section 6.2.3 */
533enum appl_error
534appl_register(const char *ctxname, uint32_t timeout, uint8_t priority,
535 struct ber_oid *oid, int instance, int subtree, uint8_t range_subid,
536 uint32_t upper_bound, struct appl_backend *backend)
537{
538 struct appl_context *ctx;
539 struct appl_region *region, search;
540 char oidbuf[1024], subidbuf[11];
541 enum appl_error error;
542 size_t i;
543 uint32_t lower_bound;
544
545 oidbuf[0] = '\0';
546 /* smi_oid2string can't do ranges */
547 for (i = 0; i < oid->bo_n; i++) {
548 snprintf(subidbuf, sizeof(subidbuf), "%"PRIu32"u", oid->bo_id[i]);
549 if (i != 0)
550 strlcat(oidbuf, ".", sizeof(oidbuf));
551 if (range_subid == i + 1) {
552 strlcat(oidbuf, "[", sizeof(oidbuf));
553 strlcat(oidbuf, subidbuf, sizeof(oidbuf));
554 strlcat(oidbuf, "-", sizeof(oidbuf));
555 snprintf(subidbuf, sizeof(subidbuf), "%"PRIu32"u",
556 upper_bound);
557 strlcat(oidbuf, subidbuf, sizeof(oidbuf));
558 strlcat(oidbuf, "]", sizeof(oidbuf));
559 } else
560 strlcat(oidbuf, subidbuf, sizeof(oidbuf));
561 }
562
563 if (ctxname == NULL((void *)0))
564 ctxname = "";
565 log_info("%s: Registering %s%s context(%s) priority(%"PRIu8"u"") "
566 "timeout(%"PRIu32"u"".%02us)", backend->ab_name, oidbuf,
567 instance ? "(instance)" : "", ctxname, priority,
568 timeout/100, timeout % 100);
569
570 if ((ctx = appl_context(ctxname, 0)) == NULL((void *)0)) {
571 if (errno(*__errno()) == ENOMEM12) {
572 log_warn("%s: Can't register %s: Processing error",
573 backend->ab_name, oidbuf);
574 return APPL_ERROR_PROCESSINGERROR;
575 }
576 log_info("%s: Can't register %s: Unsupported context \"%s\"",
577 backend->ab_name, oidbuf, ctxname);
578 return APPL_ERROR_UNSUPPORTEDCONTEXT;
579 }
580 /* Default timeouts should be handled by backend */
581 if (timeout == 0)
582 fatalx("%s: Timeout can't be 0", __func__);
583 if (priority == 0) {
584 log_warnx("%s: Can't register %s: priority can't be 0",
585 backend->ab_name, oidbuf);
586 return APPL_ERROR_PARSEERROR;
587 }
588
589 if (range_subid == 0)
590 return appl_region(ctx, timeout, priority, oid, instance,
591 subtree, backend);
592
593 range_subid--;
594 if (range_subid >= oid->bo_n) {
595 log_warnx("%s: Can't register %s: range_subid too large",
596 backend->ab_name, oidbuf);
597 return APPL_ERROR_PARSEERROR;
598 }
599 if (oid->bo_id[range_subid] > upper_bound) {
600 log_warnx("%s: Can't register %s: upper bound smaller than "
601 "range_subid", backend->ab_name, oidbuf);
602 return APPL_ERROR_PARSEERROR;
603 }
604
605 lower_bound = oid->bo_id[range_subid];
606 do {
607 if ((error = appl_region(ctx, timeout, priority, oid, instance,
608 subtree, backend)) != APPL_ERROR_NOERROR)
609 goto fail;
610 } while (oid->bo_id[range_subid]++ != upper_bound);
611 if ((error = appl_region(ctx, timeout, priority, oid, instance, subtree,
612 backend)) != APPL_ERROR_NOERROR)
613 goto fail;
614
615 return APPL_ERROR_NOERROR;
616 fail:
617 search.ar_oid = *oid;
618 if (search.ar_oid.bo_id[range_subid] == lower_bound)
619 return error;
620
621 for (search.ar_oid.bo_id[range_subid]--;
622 search.ar_oid.bo_id[range_subid] != lower_bound;
623 search.ar_oid.bo_id[range_subid]--) {
624 region = RB_FIND(appl_regions, &(ctx->ac_regions), &search)appl_regions_RB_FIND(&(ctx->ac_regions), &search);
625 while (region->ar_priority != priority)
626 region = region->ar_next;
627 appl_region_free(ctx, region);
628 }
629 region = RB_FIND(appl_regions, &(ctx->ac_regions), &search)appl_regions_RB_FIND(&(ctx->ac_regions), &search);
630 while (region->ar_priority != priority)
631 region = region->ar_next;
632 appl_region_free(ctx, region);
633 return error;
634}
635
636/* Name from RFC 2741 section 6.2.4 */
637enum appl_error
638appl_unregister(const char *ctxname, uint8_t priority, struct ber_oid *oid,
639 uint8_t range_subid, uint32_t upper_bound, struct appl_backend *backend)
640{
641 struct appl_context *ctx;
642 char oidbuf[1024], subidbuf[11];
643 enum appl_error error;
644 uint32_t lower_bound;
645 size_t i;
646
647 oidbuf[0] = '\0';
648 for (i = 0; i < oid->bo_n; i++) {
649 snprintf(subidbuf, sizeof(subidbuf), "%"PRIu32"u", oid->bo_id[i]);
650 if (i != 0)
651 strlcat(oidbuf, ".", sizeof(oidbuf));
652 if (range_subid == i + 1) {
653 strlcat(oidbuf, "[", sizeof(oidbuf));
654 strlcat(oidbuf, subidbuf, sizeof(oidbuf));
655 strlcat(oidbuf, "-", sizeof(oidbuf));
656 snprintf(subidbuf, sizeof(subidbuf), "%"PRIu32"u",
657 upper_bound);
658 strlcat(oidbuf, subidbuf, sizeof(oidbuf));
659 strlcat(oidbuf, "]", sizeof(oidbuf));
660 } else
661 strlcat(oidbuf, subidbuf, sizeof(oidbuf));
662 }
663
664 if (ctxname == NULL((void *)0))
665 ctxname = "";
666 log_info("%s: Unregistering %s context(%s) priority(%"PRIu8"u"")",
667 backend->ab_name, oidbuf,ctxname, priority);
668
669 if ((ctx = appl_context(ctxname, 0)) == NULL((void *)0)) {
670 if (errno(*__errno()) == ENOMEM12) {
671 log_warn("%s: Can't unregister %s: Processing error",
672 backend->ab_name, oidbuf);
673 return APPL_ERROR_PROCESSINGERROR;
674 }
675 log_info("%s: Can't unregister %s: Unsupported context \"%s\"",
676 backend->ab_name, oidbuf, ctxname);
677 return APPL_ERROR_UNSUPPORTEDCONTEXT;
678 }
679
680 if (priority == 0) {
681 log_warnx("%s: Can't unregister %s: priority can't be 0",
682 backend->ab_name, oidbuf);
683 return APPL_ERROR_PARSEERROR;
684 }
685
686 if (range_subid == 0)
687 return appl_region_unregister_match(ctx, priority, oid, oidbuf,
688 backend, 1);
689
690 range_subid--;
691 if (range_subid >= oid->bo_n) {
692 log_warnx("%s: Can't unregiser %s: range_subid too large",
693 backend->ab_name, oidbuf);
694 return APPL_ERROR_PARSEERROR;
695 }
696 if (oid->bo_id[range_subid] > upper_bound) {
697 log_warnx("%s: Can't unregister %s: upper bound smaller than "
698 "range_subid", backend->ab_name, oidbuf);
699 return APPL_ERROR_PARSEERROR;
700 }
701
702 lower_bound = oid->bo_id[range_subid];
703 do {
704 if ((error = appl_region_unregister_match(ctx, priority, oid,
705 oidbuf, backend, 0)) != APPL_ERROR_NOERROR)
706 return error;
707 } while (oid->bo_id[range_subid]++ != upper_bound);
708
709 oid->bo_id[range_subid] = lower_bound;
710 do {
711 (void)appl_region_unregister_match(ctx, priority, oid, oidbuf,
712 backend, 1);
713 } while (oid->bo_id[range_subid]++ != upper_bound);
714
715 return APPL_ERROR_NOERROR;
716}
717
718enum appl_error
719appl_region_unregister_match(struct appl_context *ctx, uint8_t priority,
720 struct ber_oid *oid, char *oidbuf, struct appl_backend *backend, int dofree)
721{
722 struct appl_region *region, search;
723
724 search.ar_oid = *oid;
725 region = RB_FIND(appl_regions, &(ctx->ac_regions), &search)appl_regions_RB_FIND(&(ctx->ac_regions), &search);
726 while (region != NULL((void *)0) && region->ar_priority < priority)
727 region = region->ar_next;
728 if (region == NULL((void *)0) || region->ar_priority != priority) {
729 log_warnx("%s: Can't unregister %s: region not found",
730 backend->ab_name, oidbuf);
731 return APPL_ERROR_UNKNOWNREGISTRATION;
732 }
733 if (region->ar_backend != backend) {
734 log_warnx("%s: Can't unregister %s: region not owned "
735 "by backend", backend->ab_name, oidbuf);
736 return APPL_ERROR_UNKNOWNREGISTRATION;
737 }
738 if (dofree)
739 appl_region_free(ctx, region);
740 return APPL_ERROR_NOERROR;
741}
742
743void
744appl_region_free(struct appl_context *ctx, struct appl_region *region)
745{
746 struct appl_region *pregion;
747
748 pregion = RB_FIND(appl_regions, &(ctx->ac_regions), region)appl_regions_RB_FIND(&(ctx->ac_regions), region);
749
750 if (pregion == region) {
751 RB_REMOVE(appl_regions, &(ctx->ac_regions), region)appl_regions_RB_REMOVE(&(ctx->ac_regions), region);
752 if (region->ar_next != NULL((void *)0))
753 RB_INSERT(appl_regions, &(ctx->ac_regions),appl_regions_RB_INSERT(&(ctx->ac_regions), region->
ar_next)
754 region->ar_next)appl_regions_RB_INSERT(&(ctx->ac_regions), region->
ar_next)
;
755 } else {
756 while (pregion->ar_next != region)
757 pregion = pregion->ar_next;
758 pregion->ar_next = region->ar_next;
759 }
760
761 free(region);
762}
763
764/* backend is owned by the sub-application, just release application.c stuff */
765void
766appl_close(struct appl_backend *backend)
767{
768 struct appl_context *ctx;
769 struct appl_agentcap *cap, *tcap;
770 struct appl_region *region, *tregion, *nregion;
771 struct appl_request_downstream *request, *trequest;
772
773 TAILQ_FOREACH(ctx, &contexts, ac_entries)for((ctx) = ((&contexts)->tqh_first); (ctx) != ((void *
)0); (ctx) = ((ctx)->ac_entries.tqe_next))
{
774 TAILQ_FOREACH_SAFE(cap, &(ctx->ac_agentcaps), aa_entry, tcap)for ((cap) = ((&(ctx->ac_agentcaps))->tqh_first); (
cap) != ((void *)0) && ((tcap) = ((cap)->aa_entry.
tqe_next), 1); (cap) = (tcap))
{
775 if (cap->aa_backend == backend)
776 appl_agentcap_free(cap);
777 }
778 RB_FOREACH_SAFE(region, appl_regions,for ((region) = appl_regions_RB_MINMAX(&(ctx->ac_regions
), -1); ((region) != ((void *)0)) && ((tregion) = appl_regions_RB_NEXT
(region), 1); (region) = (tregion))
779 &(ctx->ac_regions), tregion)for ((region) = appl_regions_RB_MINMAX(&(ctx->ac_regions
), -1); ((region) != ((void *)0)) && ((tregion) = appl_regions_RB_NEXT
(region), 1); (region) = (tregion))
{
780 while (region != NULL((void *)0)) {
781 nregion = region->ar_next;
782 if (region->ar_backend == backend)
783 appl_region_free(ctx, region);
784 region = nregion;
785 }
786 }
787 }
788
789 RB_FOREACH_SAFE(request, appl_requests,for ((request) = appl_requests_RB_MINMAX(&(backend->ab_requests
), -1); ((request) != ((void *)0)) && ((trequest) = appl_requests_RB_NEXT
(request), 1); (request) = (trequest))
790 &(backend->ab_requests), trequest)for ((request) = appl_requests_RB_MINMAX(&(backend->ab_requests
), -1); ((request) != ((void *)0)) && ((trequest) = appl_requests_RB_NEXT
(request), 1); (request) = (trequest))
791 appl_request_downstream_free(request);
792}
793
794struct appl_region *
795appl_region_find(struct appl_context *ctx,
796 const struct ber_oid *oid)
797{
798 struct appl_region *region, search;
799
800 search.ar_oid = *oid;
801 while (search.ar_oid.bo_n > 0) {
802 region = RB_FIND(appl_regions, &(ctx->ac_regions), &search)appl_regions_RB_FIND(&(ctx->ac_regions), &search);
803 if (region != NULL((void *)0))
804 return region;
805 search.ar_oid.bo_n--;
806 }
807 return NULL((void *)0);
808}
809
810struct appl_region *
811appl_region_next(struct appl_context *ctx, struct ber_oid *oid,
812 struct appl_region *cregion)
813{
814 struct appl_region search, *nregion, *pregion;
815 int cmp;
816
817 search.ar_oid = *oid;
818 nregion = RB_NFIND(appl_regions, &(ctx->ac_regions), &search)appl_regions_RB_NFIND(&(ctx->ac_regions), &search);
819
820 if (cregion == nregion)
821 nregion = RB_NEXT(appl_regions, &(ctx->ac_regions), nregion)appl_regions_RB_NEXT(nregion);
822 /* Past last element in tree, we might still have a parent */
823 if (nregion == NULL((void *)0)) {
824 search.ar_oid = cregion->ar_oid;
825 search.ar_oid.bo_n--;
826 return appl_region_find(ctx, &(search.ar_oid));
827 }
828 cmp = appl_region_cmp(cregion, nregion);
829 if (cmp >= 0)
830 fatalx("%s: wrong OID order", __func__);
831 /* Direct descendant */
832 if (cmp == -2)
833 return nregion;
834
835 /* cmp == -1 */
836 search.ar_oid = cregion->ar_oid;
837 /* Find direct next sibling */
838 ober_oid_nextsibling(&(search.ar_oid));
839 if (ober_oid_cmp(&(nregion->ar_oid), &(search.ar_oid)) == 0)
840 return nregion;
841 /* Sibling gaps go to parent, or end end at border */
842 search.ar_oid = cregion->ar_oid;
843 search.ar_oid.bo_n--;
844 pregion = appl_region_find(ctx, &(search.ar_oid));
845
846 return pregion != NULL((void *)0) ? pregion : nregion;
847}
848
849/* Name from RFC 3413 section 3.2 */
850void
851appl_processpdu(struct snmp_message *statereference, const char *ctxname,
852 enum snmp_version pduversion, struct ber_element *pdu)
853{
854 struct appl_context *ctx;
855 struct appl_request_upstream *ureq;
856 struct ber_element *varbind, *varbindlist;
857 long long nonrepeaters, maxrepetitions;
858 static uint32_t transactionid;
859 int32_t requestid;
860 size_t i, varbindlen = 0, repeaterlen;
861
862 /* pdu must be ASN.1 validated in snmpe.c */
863 (void) ober_scanf_elements(pdu, "{diie", &requestid, &nonrepeaters,
864 &maxrepetitions, &varbindlist);
865
866 /* RFC 3413, section 3.2, processPDU, item 5, final bullet */
867 if ((ctx = appl_context(ctxname, 0)) == NULL((void *)0)) {
868 snmp_target_mib.snmp_unknowncontexts++;
869 appl_report(statereference, requestid,
870 &OID(MIB_snmpUnknownContexts, 0)(struct ber_oid){ { 1, 3, 6, 1, 6, 3, 12, 1, 5, 0 }, (sizeof(
(uint32_t []) { 1, 3, 6, 1, 6, 3, 12, 1, 5, 0 }) / sizeof(uint32_t
)) }
);
871 return;
872 }
873
874 if ((ureq = malloc(sizeof(*ureq))) == NULL((void *)0))
875 fatal("malloc");
876
877 ureq->aru_ctx = ctx;
878 ureq->aru_statereference = statereference;
879 ureq->aru_transactionid = transactionid++;
880 ureq->aru_requesttype = pdu->be_type;
881 ureq->aru_responsetype = SNMP_C_RESPONSE;
882 ureq->aru_requestid = requestid;
883 ureq->aru_error = APPL_ERROR_NOERROR;
884 ureq->aru_index = 0;
885 ureq->aru_nonrepeaters = nonrepeaters;
886 ureq->aru_maxrepetitions = maxrepetitions;
887 ureq->aru_varbindlen = 0;
888 ureq->aru_locked = 0;
889 ureq->aru_pduversion = pduversion;
890
891 varbind = varbindlist->be_subbe_union.bv_sub;
892 for (; varbind != NULL((void *)0); varbind = varbind->be_next)
893 varbindlen++;
894
895 repeaterlen = varbindlen - nonrepeaters;
896 if (pdu->be_type == SNMP_C_GETBULKREQ)
897 ureq->aru_varbindlen = nonrepeaters +
898 (repeaterlen * maxrepetitions);
899 else
900 ureq->aru_varbindlen = varbindlen;
901 if ((ureq->aru_vblist = calloc(ureq->aru_varbindlen,
902 sizeof(*ureq->aru_vblist))) == NULL((void *)0))
903 fatal("malloc");
904
905 varbind = varbindlist->be_subbe_union.bv_sub;
906 /* Use aru_varbindlen in case maxrepetitions == 0 */
907 for (i = 0; i < ureq->aru_varbindlen; i++) {
908 ureq->aru_vblist[i].avi_request_upstream = ureq;
909 ureq->aru_vblist[i].avi_index = i + 1;
910 ureq->aru_vblist[i].avi_state = APPL_VBSTATE_NEW;
911 /* This can only happen with bulkreq */
912 if (varbind == NULL((void *)0)) {
913 ureq->aru_vblist[i - repeaterlen].avi_sub =
914 &(ureq->aru_vblist[i]);
915 ureq->aru_vblist[i].avi_state = APPL_VBSTATE_MUSTFILL;
916 ureq->aru_vblist[i].avi_index =
917 ureq->aru_vblist[i - repeaterlen].avi_index;
918 continue;
919 }
920 ober_get_oid(varbind->be_subbe_union.bv_sub,
921 &(ureq->aru_vblist[i].avi_varbind.av_oid));
922 ureq->aru_vblist[i].avi_origid =
923 ureq->aru_vblist[i].avi_varbind.av_oid;
924 if (i + 1 < varbindlen)
925 ureq->aru_vblist[i].avi_varbind.av_next =
926 &(ureq->aru_vblist[i + 1].avi_varbind);
927 else
928 ureq->aru_vblist[i].avi_varbind.av_next = NULL((void *)0);
929 varbind = varbind->be_next;
930 }
931
932 appl_pdu_log(NULL((void *)0), pdu->be_type, requestid, nonrepeaters,
933 maxrepetitions, &(ureq->aru_vblist[0].avi_varbind));
934
935 appl_request_upstream_resolve(ureq);
936}
937
938void
939appl_request_upstream_free(struct appl_request_upstream *ureq)
940{
941 size_t i;
942 struct appl_varbind_internal *vb;
943
944 if (ureq == NULL((void *)0))
945 return;
946
947 ureq->aru_locked = 1;
948 for (i = 0; i < ureq->aru_varbindlen && ureq->aru_vblist != NULL((void *)0); i++) {
949 vb = &(ureq->aru_vblist[i]);
950 ober_free_elements(vb->avi_varbind.av_value);
951 appl_request_downstream_free(vb->avi_request_downstream);
952 }
953 free(ureq->aru_vblist);
954
955 assert(ureq->aru_statereference == NULL)((ureq->aru_statereference == ((void *)0)) ? (void)0 : __assert2
("/usr/src/usr.sbin/snmpd/application.c", 955, __func__, "ureq->aru_statereference == NULL"
))
;
956
957 free(ureq);
958}
959
960void
961appl_request_downstream_free(struct appl_request_downstream *dreq)
962{
963 struct appl_varbind_internal *vb;
964
965 if (dreq
15.1
'dreq' is not equal to NULL
== NULL((void *)0))
16
Taking false branch
966 return;
967
968 RB_REMOVE(appl_requests, &(dreq->ard_backend->ab_requests), dreq)appl_requests_RB_REMOVE(&(dreq->ard_backend->ab_requests
), dreq)
;
969 evtimer_del(&(dreq->ard_timer))event_del(&(dreq->ard_timer));
970
971 for (vb = dreq->ard_vblist; vb != NULL((void *)0); vb = vb->avi_next) {
17
Assuming 'vb' is equal to NULL
18
Loop condition is false. Execution continues on line 977
972 vb->avi_request_downstream = NULL((void *)0);
973 if (vb->avi_state == APPL_VBSTATE_PENDING)
974 vb->avi_state = APPL_VBSTATE_NEW;
975 }
976
977 appl_request_upstream_resolve(dreq->ard_request);
19
Calling 'appl_request_upstream_resolve'
978 free(dreq);
979}
980
981void
982appl_request_upstream_resolve(struct appl_request_upstream *ureq)
983{
984 struct appl_varbind_internal *vb, *lvb, *tvb;
985 struct appl_request_downstream *dreq;
986 struct appl_region *region, *lregion;
987 struct timeval tv;
988 int done;
989 size_t i;
990 int32_t maxrepetitions;
991 int32_t timeout;
992
993 if (ureq->aru_locked)
20
Assuming field 'aru_locked' is 0
21
Taking false branch
994 return;
995 ureq->aru_locked = 1;
996
997 if (ureq->aru_requesttype == SNMP_C_SETREQ) {
22
Assuming field 'aru_requesttype' is not equal to SNMP_C_SETREQ
23
Taking false branch
998 ureq->aru_error = APPL_ERROR_NOTWRITABLE;
999 ureq->aru_index = 1;
1000 appl_request_upstream_reply(ureq);
1001 return;
1002 }
1003
1004 next:
1005 dreq = NULL((void *)0);
1006 lvb = NULL((void *)0);
1007 done = 1;
1008 timeout = 0;
1009
1010 if (ureq->aru_error != APPL_ERROR_NOERROR) {
24
Assuming field 'aru_error' is equal to APPL_ERROR_NOERROR
25
Taking false branch
1011 appl_request_upstream_reply(ureq);
1012 return;
1013 }
1014 for (i = 0; i < ureq->aru_varbindlen; i++) {
26
Assuming 'i' is < field 'aru_varbindlen'
27
Loop condition is true. Entering loop body
45
Assuming 'i' is >= field 'aru_varbindlen'
46
Loop condition is false. Execution continues on line 1033
1015 vb = &(ureq->aru_vblist[i]);
1016
1017 switch (vb->avi_state) {
28
Control jumps to 'case APPL_VBSTATE_NEW:' at line 1024
1018 case APPL_VBSTATE_MUSTFILL:
1019 case APPL_VBSTATE_PENDING:
1020 done = 0;
1021 continue;
1022 case APPL_VBSTATE_DONE:
1023 continue;
1024 case APPL_VBSTATE_NEW:
1025 break;
1026 }
1027 if (appl_varbind_backend(vb) == -1)
29
Execution continues on line 1027
30
Calling 'appl_varbind_backend'
41
Returning from 'appl_varbind_backend'
42
Taking false branch
1028 fatal("appl_varbind_backend");
1029 if (vb->avi_state != APPL_VBSTATE_DONE)
43
Assuming field 'avi_state' is equal to APPL_VBSTATE_DONE
44
Taking false branch
1030 done = 0;
1031 }
1032
1033 for (i = 0; i < ureq->aru_varbindlen; i++) {
47
Loop condition is true. Entering loop body
50
Loop condition is false. Execution continues on line 1110
1034 vb = &(ureq->aru_vblist[i]);
1035
1036 if (vb->avi_state
47.1
Field 'avi_state' is not equal to APPL_VBSTATE_NEW
!= APPL_VBSTATE_NEW)
48
Taking true branch
1037 continue;
49
Execution continues on line 1033
1038
1039 vb = &(ureq->aru_vblist[i]);
1040 region = vb->avi_region;
1041 lregion = lvb != NULL((void *)0) ? lvb->avi_region : NULL((void *)0);
1042 if (lvb != NULL((void *)0) && region->ar_backend != lregion->ar_backend)
1043 continue;
1044
1045 vb->avi_varbind.av_next = NULL((void *)0);
1046 vb->avi_next = NULL((void *)0);
1047 tvb = vb;
1048 for (maxrepetitions = 0; tvb != NULL((void *)0); tvb = tvb->avi_sub)
1049 maxrepetitions++;
1050 if (dreq == NULL((void *)0)) {
1051 if ((dreq = malloc(sizeof(*dreq))) == NULL((void *)0))
1052 fatal("malloc");
1053
1054 dreq->ard_request = ureq;
1055 dreq->ard_vblist = vb;
1056 dreq->ard_backend = vb->avi_region->ar_backend;
1057 dreq->ard_retries = dreq->ard_backend->ab_retries;
1058 dreq->ard_requesttype = ureq->aru_requesttype;
1059 /*
1060 * We don't yet fully handle bulkrequest responses.
1061 * It's completely valid to map onto getrequest.
1062 * maxrepetitions calculated in preparation of support.
1063 */
1064 if (dreq->ard_requesttype == SNMP_C_GETBULKREQ &&
1065 dreq->ard_backend->ab_fn->ab_getbulk == NULL((void *)0))
1066 dreq->ard_requesttype = SNMP_C_GETNEXTREQ;
1067 /*
1068 * If first varbind is nonrepeater, set maxrepetitions
1069 * to 0, so that the next varbind with
1070 * maxrepetitions > 1 determines length.
1071 */
1072 if (maxrepetitions == 1) {
1073 dreq->ard_maxrepetitions = 0;
1074 dreq->ard_nonrepeaters = 1;
1075 } else {
1076 dreq->ard_maxrepetitions = maxrepetitions;
1077 dreq->ard_nonrepeaters = 0;
1078 }
1079 do {
1080 dreq->ard_requestid = arc4random();
1081 } while (RB_INSERT(appl_requests,appl_requests_RB_INSERT(&(dreq->ard_backend->ab_requests
), dreq)
1082 &(dreq->ard_backend->ab_requests), dreq)appl_requests_RB_INSERT(&(dreq->ard_backend->ab_requests
), dreq)
!= NULL((void *)0));
1083 lvb = vb;
1084 /* avi_sub isn't set on !bulkrequest, so we always enter here */
1085 } else if (maxrepetitions == 1) {
1086 dreq->ard_nonrepeaters++;
1087 vb->avi_varbind.av_next =
1088 &(dreq->ard_vblist->avi_varbind);
1089 vb->avi_next = dreq->ard_vblist;
1090 dreq->ard_vblist = vb;
1091 } else {
1092 lvb->avi_varbind.av_next = &(vb->avi_varbind);
1093 lvb->avi_next = vb;
1094 /* RFC 2741 section 7.2.1.3:
1095 * The value of g.max_repetitions in the GetBulk-PDU may
1096 * be less than (but not greater than) the value in the
1097 * original request PDU.
1098 */
1099 if (dreq->ard_maxrepetitions > maxrepetitions ||
1100 dreq->ard_maxrepetitions == 0)
1101 dreq->ard_maxrepetitions = maxrepetitions;
1102 lvb = vb;
1103 }
1104 vb->avi_request_downstream = dreq;
1105 vb->avi_state = APPL_VBSTATE_PENDING;
1106 if (region->ar_timeout > timeout)
1107 timeout = region->ar_timeout;
1108 }
1109
1110 if (dreq
50.1
'dreq' is equal to NULL
== NULL((void *)0)) {
51
Taking true branch
1111 ureq->aru_locked = 0;
1112 if (done
51.1
'done' is 1
)
52
Taking true branch
1113 appl_request_upstream_reply(ureq);
53
Calling 'appl_request_upstream_reply'
1114 return;
1115 }
1116
1117 tv.tv_sec = timeout / 100;
1118 tv.tv_usec = (timeout % 100) * 10000;
1119 evtimer_set(&(dreq->ard_timer), appl_request_downstream_timeout, dreq)event_set(&(dreq->ard_timer), -1, 0, appl_request_downstream_timeout
, dreq)
;
1120 evtimer_add(&(dreq->ard_timer), &tv)event_add(&(dreq->ard_timer), &tv);
1121
1122 appl_request_downstream_send(dreq);
1123 goto next;
1124}
1125
1126void
1127appl_request_downstream_send(struct appl_request_downstream *dreq)
1128{
1129
1130 appl_pdu_log(dreq->ard_backend, dreq->ard_requesttype,
1131 dreq->ard_requestid, 0, 0, &(dreq->ard_vblist->avi_varbind));
1132
1133 if (dreq->ard_requesttype == SNMP_C_GETREQ) {
1134 dreq->ard_backend->ab_fn->ab_get(dreq->ard_backend,
1135 dreq->ard_request->aru_transactionid,
1136 dreq->ard_requestid,
1137 APPL_CONTEXT_NAME(dreq->ard_request->aru_ctx)(dreq->ard_request->aru_ctx->ac_name[0] == '\0' ? ((
void *)0) : dreq->ard_request->aru_ctx->ac_name)
,
1138 &(dreq->ard_vblist->avi_varbind));
1139 } else if (dreq->ard_requesttype == SNMP_C_GETNEXTREQ) {
1140 dreq->ard_backend->ab_fn->ab_getnext(dreq->ard_backend,
1141 dreq->ard_request->aru_transactionid,
1142 dreq->ard_requestid,
1143 APPL_CONTEXT_NAME(dreq->ard_request->aru_ctx)(dreq->ard_request->aru_ctx->ac_name[0] == '\0' ? ((
void *)0) : dreq->ard_request->aru_ctx->ac_name)
,
1144 &(dreq->ard_vblist->avi_varbind));
1145 }
1146}
1147
1148void
1149appl_request_downstream_timeout(__unused__attribute__((__unused__)) int fd, __unused__attribute__((__unused__)) short event,
1150 void *cookie)
1151{
1152 struct appl_request_downstream *dreq = cookie;
1153
1154 log_info("%s: %"PRIu32"u"" timed out%s",
1155 dreq->ard_backend->ab_name, dreq->ard_requestid,
1156 dreq->ard_retries > 0 ? ": retrying" : "");
1
Assuming field 'ard_retries' is <= 0
2
'?' condition is false
1157 if (dreq->ard_retries
2.1
Field 'ard_retries' is <= 0
> 0) {
3
Taking false branch
1158 dreq->ard_retries--;
1159 appl_request_downstream_send(dreq);
1160 } else
1161 appl_response(dreq->ard_backend, dreq->ard_requestid,
4
Calling 'appl_response'
1162 APPL_ERROR_GENERR, 1, &(dreq->ard_vblist->avi_varbind));
1163}
1164
1165void
1166appl_request_upstream_reply(struct appl_request_upstream *ureq)
1167{
1168 struct ber_element *varbindlist = NULL((void *)0), *varbind = NULL((void *)0), *value;
1169 struct appl_varbind_internal *vb;
1170 size_t i, repvarbinds, varbindlen;
1171 ssize_t match = -1;
1172
1173 varbindlen = ureq->aru_varbindlen;
1174
1175 if (ureq->aru_pduversion == SNMP_V1) {
54
Assuming field 'aru_pduversion' is equal to SNMP_V1
55
Taking true branch
1176 /* RFC 3584 section 4.2.2.2 Map exceptions */
1177 for (i = 0; i < varbindlen; i++) {
56
Loop condition is true. Entering loop body
58
Loop condition is false. Execution continues on line 1185
1178 vb = &(ureq->aru_vblist[i]);
1179 value = vb->avi_varbind.av_value;
1180 if (value != NULL((void *)0) &&
57
Assuming 'value' is equal to NULL
1181 value->be_class == BER_CLASS_CONTEXT0x2)
1182 appl_varbind_error(vb, APPL_ERROR_NOSUCHNAME);
1183 }
1184 /* RFC 3584 section 4.4 Map errors */
1185 switch (ureq->aru_error) {
59
Control jumps to the 'default' case at line 1205
1186 case APPL_ERROR_WRONGVALUE:
1187 case APPL_ERROR_WRONGENCODING:
1188 case APPL_ERROR_WRONGTYPE:
1189 case APPL_ERROR_WRONGLENGTH:
1190 case APPL_ERROR_INCONSISTENTVALUE:
1191 ureq->aru_error = APPL_ERROR_BADVALUE;
1192 break;
1193 case APPL_ERROR_NOACCESS:
1194 case APPL_ERROR_NOTWRITABLE:
1195 case APPL_ERROR_NOCREATION:
1196 case APPL_ERROR_INCONSISTENTNAME:
1197 case APPL_ERROR_AUTHORIZATIONERROR:
1198 ureq->aru_error = APPL_ERROR_NOSUCHNAME;
1199 break;
1200 case APPL_ERROR_RESOURCEUNAVAILABLE:
1201 case APPL_ERROR_COMMITFAILED:
1202 case APPL_ERROR_UNDOFAILED:
1203 ureq->aru_error = APPL_ERROR_GENERR;
1204 break;
1205 default:
1206 break;
60
Execution continues on line 1210
1207 }
1208 }
1209 /* RFC 3416 section 4.2.{1,2,3} reset original varbinds */
1210 if (ureq->aru_error
60.1
Field 'aru_error' is equal to APPL_ERROR_NOERROR
!= APPL_ERROR_NOERROR) {
61
Taking false branch
1211 if (ureq->aru_requesttype == SNMP_C_GETBULKREQ)
1212 varbindlen =
1213 (ureq->aru_varbindlen - ureq->aru_nonrepeaters) /
1214 ureq->aru_maxrepetitions;
1215 for (i = 0; i < varbindlen; i++) {
1216 vb = &(ureq->aru_vblist[i]);
1217 vb->avi_varbind.av_oid = vb->avi_origid;
1218 ober_free_elements(vb->avi_varbind.av_value);
1219 vb->avi_varbind.av_value = ober_add_null(NULL((void *)0));
1220 }
1221 /* RFC 3416 section 4.2.3: Strip excessive EOMV */
1222 } else if (ureq->aru_requesttype == SNMP_C_GETBULKREQ) {
62
Assuming field 'aru_requesttype' is not equal to SNMP_C_GETBULKREQ
63
Taking false branch
1223 repvarbinds = (ureq->aru_varbindlen - ureq->aru_nonrepeaters) /
1224 ureq->aru_maxrepetitions;
1225 for (i = ureq->aru_nonrepeaters;
1226 i < ureq->aru_varbindlen - repvarbinds; i++) {
1227 value = ureq->aru_vblist[i].avi_varbind.av_value;
1228 if ((i - ureq->aru_nonrepeaters) % repvarbinds == 0 &&
1229 value->be_class == BER_CLASS_CONTEXT0x2 &&
1230 value->be_type == APPL_EXC_ENDOFMIBVIEW) {
1231 if (match != -1)
1232 break;
1233 match = i;
1234 }
1235 if (value->be_class != BER_CLASS_CONTEXT0x2 ||
1236 value->be_type != APPL_EXC_ENDOFMIBVIEW)
1237 match = -1;
1238 }
1239 if (match != -1)
1240 varbindlen = match + repvarbinds;
1241 }
1242
1243 for (i = 0; i < varbindlen; i++) {
64
Loop condition is true. Entering loop body
1244 vb = &(ureq->aru_vblist[i]);
1245 vb->avi_varbind.av_next =
1246 &(ureq->aru_vblist[i + 1].avi_varbind);
1247 value = vb->avi_varbind.av_value;
65
Null pointer value stored to 'value'
1248 if (value->be_class == BER_CLASS_CONTEXT0x2 &&
66
Access to field 'be_class' results in a dereference of a null pointer (loaded from variable 'value')
1249 value->be_type == APPL_EXC_ENDOFMIBVIEW)
1250 vb->avi_varbind.av_oid = vb->avi_origid;
1251 }
1252
1253 ureq->aru_vblist[i - 1].avi_varbind.av_next = NULL((void *)0);
1254 appl_pdu_log(NULL((void *)0), ureq->aru_responsetype, ureq->aru_requestid,
1255 ureq->aru_error, ureq->aru_index,
1256 &(ureq->aru_vblist[0].avi_varbind));
1257
1258 for (i = 0; i < varbindlen; i++) {
1259 varbind = ober_printf_elements(varbind, "{Oe}",
1260 &(ureq->aru_vblist[i].avi_varbind.av_oid),
1261 ureq->aru_vblist[i].avi_varbind.av_value);
1262 ureq->aru_vblist[i].avi_varbind.av_value = NULL((void *)0);
1263 if (varbind == NULL((void *)0))
1264 fatal("ober_printf_elements");
1265 if (varbindlist == NULL((void *)0))
1266 varbindlist = varbind;
1267 }
1268
1269 snmpe_send(ureq->aru_statereference, ureq->aru_responsetype,
1270 ureq->aru_requestid, ureq->aru_error, ureq->aru_index, varbindlist);
1271 ureq->aru_statereference = NULL((void *)0);
1272 appl_request_upstream_free(ureq);
1273}
1274
1275/* Name from RFC 2741 section 6.2.16 */
1276void
1277appl_response(struct appl_backend *backend, int32_t requestid,
1278 enum appl_error error, int16_t index, struct appl_varbind *vblist)
1279{
1280 struct appl_request_downstream *dreq, search;
1281 struct appl_request_upstream *ureq = NULL((void *)0);
1282 const char *errstr;
1283 char oidbuf[1024];
1284 struct appl_varbind *vb;
1285 struct appl_varbind_internal *origvb = NULL((void *)0);
1286 int invalid = 0;
1287 int next = 0, eomv;
1288 int32_t i;
1289
1290 appl_pdu_log(backend, SNMP_C_RESPONSE, requestid, error, index, vblist);
1291
1292 search.ard_requestid = requestid;
1293 dreq = RB_FIND(appl_requests, &(backend->ab_requests), &search)appl_requests_RB_FIND(&(backend->ab_requests), &search
)
;
1294 if (dreq
4.1
'dreq' is not equal to NULL
== NULL((void *)0)) {
5
Taking false branch
1295 log_debug("%s: %"PRIu32"u"" not outstanding",
1296 backend->ab_name, requestid);
1297 /* Continue to verify validity */
1298 } else {
1299 ureq = dreq->ard_request;
1300 next = ureq->aru_requesttype == SNMP_C_GETNEXTREQ ||
6
Assuming field 'aru_requesttype' is not equal to SNMP_C_GETNEXTREQ
1301 ureq->aru_requesttype == SNMP_C_GETBULKREQ;
7
Assuming field 'aru_requesttype' is not equal to SNMP_C_GETBULKREQ
1302 origvb = dreq->ard_vblist;
1303 if (!appl_error_valid(error, dreq->ard_requesttype)) {
8
Taking false branch
1304 log_warnx("%s: %"PRIu32"u"" Invalid error",
1305 backend->ab_name, requestid);
1306 invalid = 1;
1307 }
1308 }
1309
1310 vb = vblist;
1311 for (i = 1; vb != NULL((void *)0); vb = vb->av_next, i++) {
9
Assuming 'vb' is equal to NULL
1312 if (!appl_varbind_valid(vb, origvb, next,
1313 error != APPL_ERROR_NOERROR, backend->ab_range, &errstr)) {
1314 smi_oid2string(&(vb->av_oid), oidbuf,
1315 sizeof(oidbuf), 0);
1316 log_warnx("%s: %"PRIu32"u"" %s: %s",
1317 backend->ab_name, requestid, oidbuf, errstr);
1318 invalid = 1;
1319 }
1320 /* Transfer av_value */
1321 if (origvb != NULL((void *)0)) {
1322 if (error != APPL_ERROR_NOERROR && i == index)
1323 appl_varbind_error(origvb, error);
1324 origvb->avi_state = APPL_VBSTATE_DONE;
1325 origvb->avi_varbind.av_oid = vb->av_oid;
1326
1327 eomv = vb->av_value != NULL((void *)0) &&
1328 vb->av_value->be_class == BER_CLASS_CONTEXT0x2 &&
1329 vb->av_value->be_type == APPL_EXC_ENDOFMIBVIEW;
1330 /*
1331 * Treat results past av_oid_end for backends that
1332 * don't support searchranges as EOMV
1333 */
1334 eomv |= !backend->ab_range && next &&
1335 ober_oid_cmp(&(vb->av_oid),
1336 &(origvb->avi_varbind.av_oid_end)) >= 0;
1337 /* RFC 3584 section 4.2.2.1 */
1338 if (ureq->aru_pduversion == SNMP_V1 &&
1339 vb->av_value != NULL((void *)0) &&
1340 vb->av_value->be_class == BER_CLASS_APPLICATION0x1 &&
1341 vb->av_value->be_type == SNMP_COUNTER64) {
1342 if (next)
1343 eomv = 1;
1344 else
1345 appl_varbind_error(origvb,
1346 APPL_ERROR_NOSUCHNAME);
1347 }
1348
1349 if (eomv) {
1350 ober_free_elements(vb->av_value);
1351 origvb->avi_varbind.av_oid =
1352 origvb->avi_varbind.av_oid_end;
1353 origvb->avi_varbind.av_include = 1;
1354 vb->av_value = NULL((void *)0);
1355 origvb->avi_state = APPL_VBSTATE_NEW;
1356 }
1357 origvb->avi_varbind.av_value = vb->av_value;
1358 if (origvb->avi_varbind.av_next == NULL((void *)0) &&
1359 vb->av_next != NULL((void *)0)) {
1360 log_warnx("%s: Request %"PRIu32"u"" returned more "
1361 "varbinds then requested",
1362 backend->ab_name, requestid);
1363 invalid = 1;
1364 }
1365 if (origvb->avi_sub != NULL((void *)0) &&
1366 origvb->avi_state == APPL_VBSTATE_DONE) {
1367 origvb->avi_sub->avi_varbind.av_oid =
1368 origvb->avi_varbind.av_oid;
1369 origvb->avi_sub->avi_origid =
1370 origvb->avi_varbind.av_oid;
1371 origvb->avi_sub->avi_state = APPL_VBSTATE_NEW;
1372 }
1373 origvb = origvb->avi_next;
1374 } else {
1375 ober_free_elements(vb->av_value);
1376 vb->av_value = NULL((void *)0);
1377 }
1378 }
1379 if (error
9.1
'error' is not equal to APPL_ERROR_NOERROR
!= APPL_ERROR_NOERROR && (index
9.2
'index' is > 0
<= 0 || index
9.3
'index' is >= 'i'
>= i)) {
10
Taking true branch
1380 log_warnx("Invalid error index");
1381 invalid = 1;
1382 }
1383/* amavisd-snmp-subagent sets index to 1, no reason to crash over it. */
1384#if PEDANTIC
1385 if (error == APPL_ERROR_NOERROR && index != 0) {
1386 log_warnx("error index with no error");
1387 invalid = 1;
1388 }
1389#endif
1390 if (vb
10.1
'vb' is equal to NULL
== NULL((void *)0) && origvb != NULL((void *)0)) {
11
Assuming 'origvb' is not equal to NULL
12
Taking true branch
1391 log_warnx("%s: Request %"PRIu32"u"" returned less varbinds then "
1392 "requested", backend->ab_name, requestid);
1393 invalid = 1;
1394 }
1395
1396 if (dreq
12.1
'dreq' is not equal to NULL
!= NULL((void *)0)) {
13
Taking true branch
1397 if (invalid
13.1
'invalid' is 1
)
14
Taking true branch
1398 appl_varbind_error(dreq->ard_vblist, APPL_ERROR_GENERR);
1399 appl_request_downstream_free(dreq);
15
Calling 'appl_request_downstream_free'
1400 }
1401
1402 if (invalid && backend->ab_fn->ab_close != NULL((void *)0)) {
1403 log_warnx("%s: Closing: Too many parse errors",
1404 backend->ab_name);
1405 backend->ab_fn->ab_close(backend, APPL_CLOSE_REASONPARSEERROR);
1406 }
1407}
1408
1409int
1410appl_varbind_valid(struct appl_varbind *varbind,
1411 struct appl_varbind_internal *request, int next, int null, int range,
1412 const char **errstr)
1413{
1414 int cmp;
1415 int eomv = 0;
1416
1417 if (null)
1418 next = 0;
1419
1420 if (varbind->av_value == NULL((void *)0)) {
1421 if (!null) {
1422 *errstr = "missing value";
1423 return 0;
1424 }
1425 return 1;
1426 }
1427 if (varbind->av_value->be_class == BER_CLASS_UNIVERSAL0x0) {
1428 switch (varbind->av_value->be_type) {
1429 case BER_TYPE_NULL5:
1430 if (null)
1431 break;
1432 *errstr = "not expecting null value";
1433 return 0;
1434 case BER_TYPE_INTEGER2:
1435 case BER_TYPE_OCTETSTRING4:
1436 case BER_TYPE_OBJECT6:
1437 if (!null)
1438 break;
1439 /* FALLTHROUGH */
1440 default:
1441 *errstr = "invalid value";
1442 return 0;
1443 }
1444 } else if (varbind->av_value->be_class == BER_CLASS_APPLICATION0x1) {
1445 switch (varbind->av_value->be_type) {
1446 case SNMP_T_IPADDR:
1447 case SNMP_T_COUNTER32:
1448 case SNMP_T_GAUGE32:
1449 case SNMP_T_TIMETICKS:
1450 case SNMP_T_OPAQUE:
1451 case SNMP_T_COUNTER64:
1452 if (!null)
1453 break;
1454 /* FALLTHROUGH */
1455 default:
1456 *errstr = "expecting null value";
1457 return 0;
1458 }
1459 } else if (varbind->av_value->be_class == BER_CLASS_CONTEXT0x2) {
1460 switch (varbind->av_value->be_type) {
1461 case APPL_EXC_NOSUCHOBJECT:
1462 if (next && request != NULL((void *)0)) {
1463 *errstr = "Unexpected noSuchObject";
1464 return 0;
1465 }
1466 /* FALLTHROUGH */
1467 case APPL_EXC_NOSUCHINSTANCE:
1468 if (null) {
1469 *errstr = "expecting null value";
1470 return 0;
1471 }
1472 if (next && request != NULL((void *)0)) {
1473 *errstr = "Unexpected noSuchInstance";
1474 return 0;
1475 }
1476 break;
1477 case APPL_EXC_ENDOFMIBVIEW:
1478 if (null) {
1479 *errstr = "expecting null value";
1480 return 0;
1481 }
1482 if (!next && request != NULL((void *)0)) {
1483 *errstr = "Unexpected endOfMibView";
1484 return 0;
1485 }
1486 eomv = 1;
1487 break;
1488 default:
1489 *errstr = "invalid exception";
1490 return 0;
1491 }
1492 } else {
1493 *errstr = "invalid value";
1494 return 0;
1495 }
1496
1497 if (request == NULL((void *)0))
1498 return 1;
1499
1500 cmp = ober_oid_cmp(&(request->avi_varbind.av_oid), &(varbind->av_oid));
1501 if (next) {
1502 if (request->avi_region->ar_instance &&
1503 ober_oid_cmp(&(request->avi_region->ar_oid),
1504 &(varbind->av_oid)) != 0) {
1505 *errstr = "oid below instance";
1506 return 0;
1507 }
1508 if (!eomv) {
1509 if (request->avi_varbind.av_include) {
1510 if (cmp > 0) {
1511 *errstr = "oid not incrementing";
1512 return 0;
1513 }
1514 } else {
1515 if (cmp >= 0) {
1516 *errstr = "oid not incrementing";
1517 return 0;
1518 }
1519 }
1520 if (range && ober_oid_cmp(&(varbind->av_oid),
1521 &(request->avi_varbind.av_oid_end)) >= 0) {
1522 *errstr = "end oid not honoured";
1523 return 0;
1524 }
1525 }
1526 } else {
1527 if (cmp != 0) {
1528 *errstr = "oids not equal";
1529 return 0;
1530 }
1531 }
1532 return 1;
1533}
1534
1535int
1536appl_error_valid(enum appl_error error, enum snmp_pdutype type)
1537{
1538 switch (error) {
1539 case APPL_ERROR_NOERROR:
1540 case APPL_ERROR_TOOBIG:
1541 case APPL_ERROR_NOSUCHNAME:
1542 case APPL_ERROR_GENERR:
1543 return 1;
1544 case APPL_ERROR_BADVALUE:
1545 case APPL_ERROR_READONLY:
1546 case APPL_ERROR_NOACCESS:
1547 case APPL_ERROR_WRONGTYPE:
1548 case APPL_ERROR_WRONGLENGTH:
1549 case APPL_ERROR_WRONGENCODING:
1550 case APPL_ERROR_WRONGVALUE:
1551 case APPL_ERROR_NOCREATION:
1552 case APPL_ERROR_INCONSISTENTVALUE:
1553 case APPL_ERROR_RESOURCEUNAVAILABLE:
1554 case APPL_ERROR_COMMITFAILED:
1555 case APPL_ERROR_UNDOFAILED:
1556 case APPL_ERROR_NOTWRITABLE:
1557 case APPL_ERROR_INCONSISTENTNAME:
1558 return type == SNMP_C_SETREQ;
1559 case APPL_ERROR_AUTHORIZATIONERROR:
1560 return type == SNMP_C_GETREQ || type == SNMP_C_SETREQ;
1561 default:
1562 return 0;
1563 }
1564}
1565
1566int
1567appl_varbind_backend(struct appl_varbind_internal *ivb)
1568{
1569 struct appl_request_upstream *ureq = ivb->avi_request_upstream;
1570 struct appl_region search, *region, *pregion;
1571 struct appl_varbind *vb = &(ivb->avi_varbind);
1572 struct ber_oid oid, nextsibling;
1573 int next, cmp;
1574
1575 next = ureq->aru_requesttype == SNMP_C_GETNEXTREQ ||
31
Assuming field 'aru_requesttype' is not equal to SNMP_C_GETNEXTREQ
1576 ureq->aru_requesttype == SNMP_C_GETBULKREQ;
32
Assuming field 'aru_requesttype' is not equal to SNMP_C_GETBULKREQ
1577
1578 region = appl_region_find(ureq->aru_ctx, &(vb->av_oid));
1579 if (region == NULL((void *)0)) {
33
Assuming 'region' is not equal to NULL
34
Taking false branch
1580 if (!next) {
1581 vb->av_value = appl_exception(APPL_EXC_NOSUCHOBJECT);
1582 ivb->avi_state = APPL_VBSTATE_DONE;
1583 if (vb->av_value == NULL((void *)0))
1584 return -1;
1585 return 0;
1586 }
1587 search.ar_oid = vb->av_oid;
1588 region = RB_NFIND(appl_regions,appl_regions_RB_NFIND(&(ureq->aru_ctx->ac_regions),
&search)
1589 &(ureq->aru_ctx->ac_regions), &search)appl_regions_RB_NFIND(&(ureq->aru_ctx->ac_regions),
&search)
;
1590 if (region == NULL((void *)0))
1591 goto eomv;
1592 vb->av_oid = region->ar_oid;
1593 vb->av_include = 1;
1594 }
1595 cmp = ober_oid_cmp(&(region->ar_oid), &(vb->av_oid));
35
Value assigned to field 'av_value'
1596 if (cmp == -2) {
36
Assuming the condition is false
37
Taking false branch
1597 if (region->ar_instance) {
1598 if (!next) {
1599 vb->av_value =
1600 appl_exception(APPL_EXC_NOSUCHINSTANCE);
1601 ivb->avi_state = APPL_VBSTATE_DONE;
1602 if (vb->av_value == NULL((void *)0))
1603 return -1;
1604 return 0;
1605 }
1606 vb->av_oid = region->ar_oid;
1607 ober_oid_nextsibling(&(vb->av_oid));
1608 vb->av_include = 1;
1609 return appl_varbind_backend(ivb);
1610 }
1611 } else if (cmp == 0) {
38
Assuming 'cmp' is not equal to 0
39
Taking false branch
1612 if (region->ar_instance && next && !vb->av_include) {
1613 vb->av_oid = region->ar_oid;
1614 ober_oid_nextsibling(&(vb->av_oid));
1615 vb->av_include = 1;
1616 return appl_varbind_backend(ivb);
1617 }
1618 }
1619 ivb->avi_region = region;
1620 if (next
39.1
'next' is 0
) {
40
Taking false branch
1621 oid = vb->av_oid;
1622 /*
1623 * For the searchrange end we only want contiguous regions.
1624 * This means directly connecting, or overlapping with the same
1625 * backend.
1626 */
1627 do {
1628 pregion = region;
1629 region = appl_region_next(ureq->aru_ctx, &oid, pregion);
1630 if (region == NULL((void *)0)) {
1631 oid = pregion->ar_oid;
1632 ober_oid_nextsibling(&oid);
1633 break;
1634 }
1635 cmp = ober_oid_cmp(&(region->ar_oid), &oid);
1636 if (cmp == 2)
1637 oid = region->ar_oid;
1638 else if (cmp == 1) {
1639 /* Break out if we find a gap */
1640 nextsibling = pregion->ar_oid;
1641 ober_oid_nextsibling(&nextsibling);
1642 if (ober_oid_cmp(&(region->ar_oid),
1643 &nextsibling) != 0) {
1644 oid = pregion->ar_oid;
1645 ober_oid_nextsibling(&oid);
1646 break;
1647 }
1648 oid = region->ar_oid;
1649 } else if (cmp == -2) {
1650 oid = pregion->ar_oid;
1651 ober_oid_nextsibling(&oid);
1652 } else
1653 fatalx("We can't stop/move back on getnext");
1654 } while (region->ar_backend == pregion->ar_backend);
1655 vb->av_oid_end = oid;
1656 }
1657 return 0;
1658
1659 eomv:
1660 do {
1661 ivb->avi_varbind.av_value =
1662 appl_exception(APPL_EXC_ENDOFMIBVIEW);
1663 ivb->avi_state = APPL_VBSTATE_DONE;
1664 if (ivb->avi_varbind.av_value == NULL((void *)0))
1665 return -1;
1666 if (ivb->avi_sub != NULL((void *)0)) {
1667 ivb->avi_sub->avi_varbind.av_oid =
1668 ivb->avi_varbind.av_oid;
1669 ivb->avi_sub->avi_origid = ivb->avi_origid;
1670 }
1671 ivb = ivb->avi_sub;
1672 } while (ivb != NULL((void *)0));
1673
1674 return 0;
1675}
1676
1677void
1678appl_varbind_error(struct appl_varbind_internal *avi, enum appl_error error)
1679{
1680 struct appl_request_upstream *ureq = avi->avi_request_upstream;
1681
1682 if (ureq->aru_error == APPL_ERROR_GENERR)
1683 return;
1684 if (ureq->aru_error != APPL_ERROR_NOERROR && error != APPL_ERROR_GENERR)
1685 return;
1686 ureq->aru_error = error;
1687 ureq->aru_index = avi->avi_index;
1688}
1689
1690void
1691appl_report(struct snmp_message *statereference, int32_t requestid,
1692 struct ber_oid *oid)
1693{
1694 struct appl_request_upstream *ureq;
1695
1696 if ((ureq = calloc(1, sizeof(*ureq))) == NULL((void *)0))
1697 fatal("malloc");
1698 ureq->aru_ctx = appl_context(NULL((void *)0), 0);
1699 ureq->aru_statereference = statereference;
1700 ureq->aru_requesttype = SNMP_C_GETREQ;
1701 ureq->aru_responsetype = SNMP_C_REPORT;
1702 ureq->aru_requestid = requestid;
1703 ureq->aru_transactionid = 0;
1704 ureq->aru_nonrepeaters = 0;
1705 ureq->aru_maxrepetitions = 0;
1706 if ((ureq->aru_vblist = calloc(1, sizeof(*ureq->aru_vblist))) == NULL((void *)0))
1707 fatal("malloc");
1708 ureq->aru_varbindlen = 1;
1709 ureq->aru_error = APPL_ERROR_NOERROR;
1710 ureq->aru_index = 0;
1711 ureq->aru_locked = 0;
1712 ureq->aru_pduversion = SNMP_V3;
1713
1714 ureq->aru_vblist[0].avi_state = APPL_VBSTATE_NEW;
1715 ureq->aru_vblist[0].avi_varbind.av_oid = *oid;
1716 ureq->aru_vblist[0].avi_varbind.av_value = NULL((void *)0);
1717 ureq->aru_vblist[0].avi_varbind.av_next = NULL((void *)0);
1718 ureq->aru_vblist[0].avi_origid = *oid;
1719 ureq->aru_vblist[0].avi_index = 1;
1720 ureq->aru_vblist[0].avi_request_upstream = ureq;
1721 ureq->aru_vblist[0].avi_request_downstream = NULL((void *)0);
1722 ureq->aru_vblist[0].avi_next = NULL((void *)0);
1723 ureq->aru_vblist[0].avi_sub = NULL((void *)0);
1724
1725 appl_request_upstream_resolve(ureq);
1726}
1727
1728struct ber_element *
1729appl_exception(enum appl_exception type)
1730{
1731 struct ber_element *value;
1732
1733 if ((value = ober_add_null(NULL((void *)0))) == NULL((void *)0)) {
1734 log_warn("malloc");
1735 return NULL((void *)0);
1736 }
1737 ober_set_header(value, BER_CLASS_CONTEXT0x2, type);
1738
1739 return value;
1740}
1741
1742void
1743appl_pdu_log(struct appl_backend *backend, enum snmp_pdutype pdutype,
1744 int32_t requestid, uint16_t error, uint16_t index,
1745 struct appl_varbind *vblist)
1746{
1747 struct appl_varbind *vb;
1748 char buf[1024], oidbuf[1024], *str;
1749 int next;
1750
1751 if (log_getverbose() < 2)
1752 return;
1753
1754 next = (pdutype == SNMP_C_GETNEXTREQ || pdutype == SNMP_C_GETBULKREQ);
1755
1756 buf[0] = '\0';
1757 for (vb = vblist; vb != NULL((void *)0); vb = vb->av_next) {
1758 strlcat(buf, "{", sizeof(buf));
1759 strlcat(buf, smi_oid2string(&(vb->av_oid), oidbuf,
1760 sizeof(oidbuf), 0), sizeof(buf));
1761 if (next) {
1762 if (vb->av_include)
1763 strlcat(buf, "(incl)", sizeof(buf));
1764 if (vb->av_oid_end.bo_n > 0) {
1765 strlcat(buf, "-", sizeof(buf));
1766 strlcat(buf, smi_oid2string(&(vb->av_oid_end),
1767 oidbuf, sizeof(oidbuf), 0), sizeof(buf));
1768 }
1769 }
1770 strlcat(buf, ":", sizeof(buf));
1771 if (vb->av_value != NULL((void *)0)) {
1772 str = smi_print_element(vb->av_value);
1773 strlcat(buf, str == NULL((void *)0) ? "???" : str, sizeof(buf));
1774 free(str);
1775 } else
1776 strlcat(buf, "null", sizeof(buf));
1777 strlcat(buf, "}", sizeof(buf));
1778 }
1779 log_debug("%s%s%s{%"PRId32"d"", %"PRIu16"u"", %"PRIu16"u"", {%s}}",
1780 backend != NULL((void *)0) ? backend->ab_name : "",
1781 backend != NULL((void *)0) ? ": " : "",
1782 snmpe_pdutype2string(pdutype), requestid, error, index, buf);
1783}
1784
1785void
1786ober_oid_nextsibling(struct ber_oid *oid)
1787{
1788 while (oid->bo_n > 0) {
1789 oid->bo_id[oid->bo_n - 1]++;
1790 /* Overflow check */
1791 if (oid->bo_id[oid->bo_n - 1] != 0)
1792 return;
1793 oid->bo_n--;
1794 }
1795}
1796
1797int
1798appl_region_cmp(struct appl_region *r1, struct appl_region *r2)
1799{
1800 return ober_oid_cmp(&(r1->ar_oid), &(r2->ar_oid));
1801}
1802
1803int
1804appl_request_cmp(struct appl_request_downstream *r1,
1805 struct appl_request_downstream *r2)
1806{
1807 return r1->ard_requestid < r2->ard_requestid ? -1 :
1808 r1->ard_requestid > r2->ard_requestid;
1809}
1810
1811RB_GENERATE_STATIC(appl_regions, appl_region, ar_entry, appl_region_cmp)__attribute__((__unused__)) static void appl_regions_RB_INSERT_COLOR
(struct appl_regions *head, struct appl_region *elm) { struct
appl_region *parent, *gparent, *tmp; while ((parent = (elm)->
ar_entry.rbe_parent) && (parent)->ar_entry.rbe_color
== 1) { gparent = (parent)->ar_entry.rbe_parent; if (parent
== (gparent)->ar_entry.rbe_left) { tmp = (gparent)->ar_entry
.rbe_right; if (tmp && (tmp)->ar_entry.rbe_color ==
1) { (tmp)->ar_entry.rbe_color = 0; do { (parent)->ar_entry
.rbe_color = 0; (gparent)->ar_entry.rbe_color = 1; } while
(0); elm = gparent; continue; } if ((parent)->ar_entry.rbe_right
== elm) { do { (tmp) = (parent)->ar_entry.rbe_right; if (
((parent)->ar_entry.rbe_right = (tmp)->ar_entry.rbe_left
)) { ((tmp)->ar_entry.rbe_left)->ar_entry.rbe_parent = (
parent); } do {} while (0); if (((tmp)->ar_entry.rbe_parent
= (parent)->ar_entry.rbe_parent)) { if ((parent) == ((parent
)->ar_entry.rbe_parent)->ar_entry.rbe_left) ((parent)->
ar_entry.rbe_parent)->ar_entry.rbe_left = (tmp); else ((parent
)->ar_entry.rbe_parent)->ar_entry.rbe_right = (tmp); } else
(head)->rbh_root = (tmp); (tmp)->ar_entry.rbe_left = (
parent); (parent)->ar_entry.rbe_parent = (tmp); do {} while
(0); if (((tmp)->ar_entry.rbe_parent)) do {} while (0); }
while (0); tmp = parent; parent = elm; elm = tmp; } do { (parent
)->ar_entry.rbe_color = 0; (gparent)->ar_entry.rbe_color
= 1; } while (0); do { (tmp) = (gparent)->ar_entry.rbe_left
; if (((gparent)->ar_entry.rbe_left = (tmp)->ar_entry.rbe_right
)) { ((tmp)->ar_entry.rbe_right)->ar_entry.rbe_parent =
(gparent); } do {} while (0); if (((tmp)->ar_entry.rbe_parent
= (gparent)->ar_entry.rbe_parent)) { if ((gparent) == ((gparent
)->ar_entry.rbe_parent)->ar_entry.rbe_left) ((gparent)->
ar_entry.rbe_parent)->ar_entry.rbe_left = (tmp); else ((gparent
)->ar_entry.rbe_parent)->ar_entry.rbe_right = (tmp); } else
(head)->rbh_root = (tmp); (tmp)->ar_entry.rbe_right = (
gparent); (gparent)->ar_entry.rbe_parent = (tmp); do {} while
(0); if (((tmp)->ar_entry.rbe_parent)) do {} while (0); }
while (0); } else { tmp = (gparent)->ar_entry.rbe_left; if
(tmp && (tmp)->ar_entry.rbe_color == 1) { (tmp)->
ar_entry.rbe_color = 0; do { (parent)->ar_entry.rbe_color =
0; (gparent)->ar_entry.rbe_color = 1; } while (0); elm = gparent
; continue; } if ((parent)->ar_entry.rbe_left == elm) { do
{ (tmp) = (parent)->ar_entry.rbe_left; if (((parent)->
ar_entry.rbe_left = (tmp)->ar_entry.rbe_right)) { ((tmp)->
ar_entry.rbe_right)->ar_entry.rbe_parent = (parent); } do {
} while (0); if (((tmp)->ar_entry.rbe_parent = (parent)->
ar_entry.rbe_parent)) { if ((parent) == ((parent)->ar_entry
.rbe_parent)->ar_entry.rbe_left) ((parent)->ar_entry.rbe_parent
)->ar_entry.rbe_left = (tmp); else ((parent)->ar_entry.
rbe_parent)->ar_entry.rbe_right = (tmp); } else (head)->
rbh_root = (tmp); (tmp)->ar_entry.rbe_right = (parent); (parent
)->ar_entry.rbe_parent = (tmp); do {} while (0); if (((tmp
)->ar_entry.rbe_parent)) do {} while (0); } while (0); tmp
= parent; parent = elm; elm = tmp; } do { (parent)->ar_entry
.rbe_color = 0; (gparent)->ar_entry.rbe_color = 1; } while
(0); do { (tmp) = (gparent)->ar_entry.rbe_right; if (((gparent
)->ar_entry.rbe_right = (tmp)->ar_entry.rbe_left)) { ((
tmp)->ar_entry.rbe_left)->ar_entry.rbe_parent = (gparent
); } do {} while (0); if (((tmp)->ar_entry.rbe_parent = (gparent
)->ar_entry.rbe_parent)) { if ((gparent) == ((gparent)->
ar_entry.rbe_parent)->ar_entry.rbe_left) ((gparent)->ar_entry
.rbe_parent)->ar_entry.rbe_left = (tmp); else ((gparent)->
ar_entry.rbe_parent)->ar_entry.rbe_right = (tmp); } else (
head)->rbh_root = (tmp); (tmp)->ar_entry.rbe_left = (gparent
); (gparent)->ar_entry.rbe_parent = (tmp); do {} while (0)
; if (((tmp)->ar_entry.rbe_parent)) do {} while (0); } while
(0); } } (head->rbh_root)->ar_entry.rbe_color = 0; } __attribute__
((__unused__)) static void appl_regions_RB_REMOVE_COLOR(struct
appl_regions *head, struct appl_region *parent, struct appl_region
*elm) { struct appl_region *tmp; while ((elm == ((void *)0) ||
(elm)->ar_entry.rbe_color == 0) && elm != (head)->
rbh_root) { if ((parent)->ar_entry.rbe_left == elm) { tmp =
(parent)->ar_entry.rbe_right; if ((tmp)->ar_entry.rbe_color
== 1) { do { (tmp)->ar_entry.rbe_color = 0; (parent)->
ar_entry.rbe_color = 1; } while (0); do { (tmp) = (parent)->
ar_entry.rbe_right; if (((parent)->ar_entry.rbe_right = (tmp
)->ar_entry.rbe_left)) { ((tmp)->ar_entry.rbe_left)->
ar_entry.rbe_parent = (parent); } do {} while (0); if (((tmp)
->ar_entry.rbe_parent = (parent)->ar_entry.rbe_parent))
{ if ((parent) == ((parent)->ar_entry.rbe_parent)->ar_entry
.rbe_left) ((parent)->ar_entry.rbe_parent)->ar_entry.rbe_left
= (tmp); else ((parent)->ar_entry.rbe_parent)->ar_entry
.rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp)
->ar_entry.rbe_left = (parent); (parent)->ar_entry.rbe_parent
= (tmp); do {} while (0); if (((tmp)->ar_entry.rbe_parent
)) do {} while (0); } while (0); tmp = (parent)->ar_entry.
rbe_right; } if (((tmp)->ar_entry.rbe_left == ((void *)0) ||
((tmp)->ar_entry.rbe_left)->ar_entry.rbe_color == 0) &&
((tmp)->ar_entry.rbe_right == ((void *)0) || ((tmp)->ar_entry
.rbe_right)->ar_entry.rbe_color == 0)) { (tmp)->ar_entry
.rbe_color = 1; elm = parent; parent = (elm)->ar_entry.rbe_parent
; } else { if ((tmp)->ar_entry.rbe_right == ((void *)0) ||
((tmp)->ar_entry.rbe_right)->ar_entry.rbe_color == 0) {
struct appl_region *oleft; if ((oleft = (tmp)->ar_entry.rbe_left
)) (oleft)->ar_entry.rbe_color = 0; (tmp)->ar_entry.rbe_color
= 1; do { (oleft) = (tmp)->ar_entry.rbe_left; if (((tmp)->
ar_entry.rbe_left = (oleft)->ar_entry.rbe_right)) { ((oleft
)->ar_entry.rbe_right)->ar_entry.rbe_parent = (tmp); } do
{} while (0); if (((oleft)->ar_entry.rbe_parent = (tmp)->
ar_entry.rbe_parent)) { if ((tmp) == ((tmp)->ar_entry.rbe_parent
)->ar_entry.rbe_left) ((tmp)->ar_entry.rbe_parent)->
ar_entry.rbe_left = (oleft); else ((tmp)->ar_entry.rbe_parent
)->ar_entry.rbe_right = (oleft); } else (head)->rbh_root
= (oleft); (oleft)->ar_entry.rbe_right = (tmp); (tmp)->
ar_entry.rbe_parent = (oleft); do {} while (0); if (((oleft)->
ar_entry.rbe_parent)) do {} while (0); } while (0); tmp = (parent
)->ar_entry.rbe_right; } (tmp)->ar_entry.rbe_color = (parent
)->ar_entry.rbe_color; (parent)->ar_entry.rbe_color = 0
; if ((tmp)->ar_entry.rbe_right) ((tmp)->ar_entry.rbe_right
)->ar_entry.rbe_color = 0; do { (tmp) = (parent)->ar_entry
.rbe_right; if (((parent)->ar_entry.rbe_right = (tmp)->
ar_entry.rbe_left)) { ((tmp)->ar_entry.rbe_left)->ar_entry
.rbe_parent = (parent); } do {} while (0); if (((tmp)->ar_entry
.rbe_parent = (parent)->ar_entry.rbe_parent)) { if ((parent
) == ((parent)->ar_entry.rbe_parent)->ar_entry.rbe_left
) ((parent)->ar_entry.rbe_parent)->ar_entry.rbe_left = (
tmp); else ((parent)->ar_entry.rbe_parent)->ar_entry.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->ar_entry
.rbe_left = (parent); (parent)->ar_entry.rbe_parent = (tmp
); do {} while (0); if (((tmp)->ar_entry.rbe_parent)) do {
} while (0); } while (0); elm = (head)->rbh_root; break; }
} else { tmp = (parent)->ar_entry.rbe_left; if ((tmp)->
ar_entry.rbe_color == 1) { do { (tmp)->ar_entry.rbe_color =
0; (parent)->ar_entry.rbe_color = 1; } while (0); do { (tmp
) = (parent)->ar_entry.rbe_left; if (((parent)->ar_entry
.rbe_left = (tmp)->ar_entry.rbe_right)) { ((tmp)->ar_entry
.rbe_right)->ar_entry.rbe_parent = (parent); } do {} while
(0); if (((tmp)->ar_entry.rbe_parent = (parent)->ar_entry
.rbe_parent)) { if ((parent) == ((parent)->ar_entry.rbe_parent
)->ar_entry.rbe_left) ((parent)->ar_entry.rbe_parent)->
ar_entry.rbe_left = (tmp); else ((parent)->ar_entry.rbe_parent
)->ar_entry.rbe_right = (tmp); } else (head)->rbh_root =
(tmp); (tmp)->ar_entry.rbe_right = (parent); (parent)->
ar_entry.rbe_parent = (tmp); do {} while (0); if (((tmp)->
ar_entry.rbe_parent)) do {} while (0); } while (0); tmp = (parent
)->ar_entry.rbe_left; } if (((tmp)->ar_entry.rbe_left ==
((void *)0) || ((tmp)->ar_entry.rbe_left)->ar_entry.rbe_color
== 0) && ((tmp)->ar_entry.rbe_right == ((void *)0
) || ((tmp)->ar_entry.rbe_right)->ar_entry.rbe_color ==
0)) { (tmp)->ar_entry.rbe_color = 1; elm = parent; parent
= (elm)->ar_entry.rbe_parent; } else { if ((tmp)->ar_entry
.rbe_left == ((void *)0) || ((tmp)->ar_entry.rbe_left)->
ar_entry.rbe_color == 0) { struct appl_region *oright; if ((oright
= (tmp)->ar_entry.rbe_right)) (oright)->ar_entry.rbe_color
= 0; (tmp)->ar_entry.rbe_color = 1; do { (oright) = (tmp)
->ar_entry.rbe_right; if (((tmp)->ar_entry.rbe_right = (
oright)->ar_entry.rbe_left)) { ((oright)->ar_entry.rbe_left
)->ar_entry.rbe_parent = (tmp); } do {} while (0); if (((oright
)->ar_entry.rbe_parent = (tmp)->ar_entry.rbe_parent)) {
if ((tmp) == ((tmp)->ar_entry.rbe_parent)->ar_entry.rbe_left
) ((tmp)->ar_entry.rbe_parent)->ar_entry.rbe_left = (oright
); else ((tmp)->ar_entry.rbe_parent)->ar_entry.rbe_right
= (oright); } else (head)->rbh_root = (oright); (oright)->
ar_entry.rbe_left = (tmp); (tmp)->ar_entry.rbe_parent = (oright
); do {} while (0); if (((oright)->ar_entry.rbe_parent)) do
{} while (0); } while (0); tmp = (parent)->ar_entry.rbe_left
; } (tmp)->ar_entry.rbe_color = (parent)->ar_entry.rbe_color
; (parent)->ar_entry.rbe_color = 0; if ((tmp)->ar_entry
.rbe_left) ((tmp)->ar_entry.rbe_left)->ar_entry.rbe_color
= 0; do { (tmp) = (parent)->ar_entry.rbe_left; if (((parent
)->ar_entry.rbe_left = (tmp)->ar_entry.rbe_right)) { ((
tmp)->ar_entry.rbe_right)->ar_entry.rbe_parent = (parent
); } do {} while (0); if (((tmp)->ar_entry.rbe_parent = (parent
)->ar_entry.rbe_parent)) { if ((parent) == ((parent)->ar_entry
.rbe_parent)->ar_entry.rbe_left) ((parent)->ar_entry.rbe_parent
)->ar_entry.rbe_left = (tmp); else ((parent)->ar_entry.
rbe_parent)->ar_entry.rbe_right = (tmp); } else (head)->
rbh_root = (tmp); (tmp)->ar_entry.rbe_right = (parent); (parent
)->ar_entry.rbe_parent = (tmp); do {} while (0); if (((tmp
)->ar_entry.rbe_parent)) do {} while (0); } while (0); elm
= (head)->rbh_root; break; } } } if (elm) (elm)->ar_entry
.rbe_color = 0; } __attribute__((__unused__)) static struct appl_region
* appl_regions_RB_REMOVE(struct appl_regions *head, struct appl_region
*elm) { struct appl_region *child, *parent, *old = elm; int color
; if ((elm)->ar_entry.rbe_left == ((void *)0)) child = (elm
)->ar_entry.rbe_right; else if ((elm)->ar_entry.rbe_right
== ((void *)0)) child = (elm)->ar_entry.rbe_left; else { struct
appl_region *left; elm = (elm)->ar_entry.rbe_right; while
((left = (elm)->ar_entry.rbe_left)) elm = left; child = (
elm)->ar_entry.rbe_right; parent = (elm)->ar_entry.rbe_parent
; color = (elm)->ar_entry.rbe_color; if (child) (child)->
ar_entry.rbe_parent = parent; if (parent) { if ((parent)->
ar_entry.rbe_left == elm) (parent)->ar_entry.rbe_left = child
; else (parent)->ar_entry.rbe_right = child; do {} while (
0); } else (head)->rbh_root = child; if ((elm)->ar_entry
.rbe_parent == old) parent = elm; (elm)->ar_entry = (old)->
ar_entry; if ((old)->ar_entry.rbe_parent) { if (((old)->
ar_entry.rbe_parent)->ar_entry.rbe_left == old) ((old)->
ar_entry.rbe_parent)->ar_entry.rbe_left = elm; else ((old)
->ar_entry.rbe_parent)->ar_entry.rbe_right = elm; do {}
while (0); } else (head)->rbh_root = elm; ((old)->ar_entry
.rbe_left)->ar_entry.rbe_parent = elm; if ((old)->ar_entry
.rbe_right) ((old)->ar_entry.rbe_right)->ar_entry.rbe_parent
= elm; if (parent) { left = parent; do { do {} while (0); } while
((left = (left)->ar_entry.rbe_parent)); } goto color; } parent
= (elm)->ar_entry.rbe_parent; color = (elm)->ar_entry.
rbe_color; if (child) (child)->ar_entry.rbe_parent = parent
; if (parent) { if ((parent)->ar_entry.rbe_left == elm) (parent
)->ar_entry.rbe_left = child; else (parent)->ar_entry.rbe_right
= child; do {} while (0); } else (head)->rbh_root = child
; color: if (color == 0) appl_regions_RB_REMOVE_COLOR(head, parent
, child); return (old); } __attribute__((__unused__)) static struct
appl_region * appl_regions_RB_INSERT(struct appl_regions *head
, struct appl_region *elm) { struct appl_region *tmp; struct appl_region
*parent = ((void *)0); int comp = 0; tmp = (head)->rbh_root
; while (tmp) { parent = tmp; comp = (appl_region_cmp)(elm, parent
); if (comp < 0) tmp = (tmp)->ar_entry.rbe_left; else if
(comp > 0) tmp = (tmp)->ar_entry.rbe_right; else return
(tmp); } do { (elm)->ar_entry.rbe_parent = parent; (elm)->
ar_entry.rbe_left = (elm)->ar_entry.rbe_right = ((void *)0
); (elm)->ar_entry.rbe_color = 1; } while (0); if (parent !=
((void *)0)) { if (comp < 0) (parent)->ar_entry.rbe_left
= elm; else (parent)->ar_entry.rbe_right = elm; do {} while
(0); } else (head)->rbh_root = elm; appl_regions_RB_INSERT_COLOR
(head, elm); return (((void *)0)); } __attribute__((__unused__
)) static struct appl_region * appl_regions_RB_FIND(struct appl_regions
*head, struct appl_region *elm) { struct appl_region *tmp = (
head)->rbh_root; int comp; while (tmp) { comp = appl_region_cmp
(elm, tmp); if (comp < 0) tmp = (tmp)->ar_entry.rbe_left
; else if (comp > 0) tmp = (tmp)->ar_entry.rbe_right; else
return (tmp); } return (((void *)0)); } __attribute__((__unused__
)) static struct appl_region * appl_regions_RB_NFIND(struct appl_regions
*head, struct appl_region *elm) { struct appl_region *tmp = (
head)->rbh_root; struct appl_region *res = ((void *)0); int
comp; while (tmp) { comp = appl_region_cmp(elm, tmp); if (comp
< 0) { res = tmp; tmp = (tmp)->ar_entry.rbe_left; } else
if (comp > 0) tmp = (tmp)->ar_entry.rbe_right; else return
(tmp); } return (res); } __attribute__((__unused__)) static struct
appl_region * appl_regions_RB_NEXT(struct appl_region *elm) {
if ((elm)->ar_entry.rbe_right) { elm = (elm)->ar_entry
.rbe_right; while ((elm)->ar_entry.rbe_left) elm = (elm)->
ar_entry.rbe_left; } else { if ((elm)->ar_entry.rbe_parent
&& (elm == ((elm)->ar_entry.rbe_parent)->ar_entry
.rbe_left)) elm = (elm)->ar_entry.rbe_parent; else { while
((elm)->ar_entry.rbe_parent && (elm == ((elm)->
ar_entry.rbe_parent)->ar_entry.rbe_right)) elm = (elm)->
ar_entry.rbe_parent; elm = (elm)->ar_entry.rbe_parent; } }
return (elm); } __attribute__((__unused__)) static struct appl_region
* appl_regions_RB_PREV(struct appl_region *elm) { if ((elm)->
ar_entry.rbe_left) { elm = (elm)->ar_entry.rbe_left; while
((elm)->ar_entry.rbe_right) elm = (elm)->ar_entry.rbe_right
; } else { if ((elm)->ar_entry.rbe_parent && (elm ==
((elm)->ar_entry.rbe_parent)->ar_entry.rbe_right)) elm
= (elm)->ar_entry.rbe_parent; else { while ((elm)->ar_entry
.rbe_parent && (elm == ((elm)->ar_entry.rbe_parent
)->ar_entry.rbe_left)) elm = (elm)->ar_entry.rbe_parent
; elm = (elm)->ar_entry.rbe_parent; } } return (elm); } __attribute__
((__unused__)) static struct appl_region * appl_regions_RB_MINMAX
(struct appl_regions *head, int val) { struct appl_region *tmp
= (head)->rbh_root; struct appl_region *parent = ((void *
)0); while (tmp) { parent = tmp; if (val < 0) tmp = (tmp)->
ar_entry.rbe_left; else tmp = (tmp)->ar_entry.rbe_right; }
return (parent); }
;
1812RB_GENERATE_STATIC(appl_requests, appl_request_downstream, ard_entry,__attribute__((__unused__)) static void appl_requests_RB_INSERT_COLOR
(struct appl_requests *head, struct appl_request_downstream *
elm) { struct appl_request_downstream *parent, *gparent, *tmp
; while ((parent = (elm)->ard_entry.rbe_parent) &&
(parent)->ard_entry.rbe_color == 1) { gparent = (parent)->
ard_entry.rbe_parent; if (parent == (gparent)->ard_entry.rbe_left
) { tmp = (gparent)->ard_entry.rbe_right; if (tmp &&
(tmp)->ard_entry.rbe_color == 1) { (tmp)->ard_entry.rbe_color
= 0; do { (parent)->ard_entry.rbe_color = 0; (gparent)->
ard_entry.rbe_color = 1; } while (0); elm = gparent; continue
; } if ((parent)->ard_entry.rbe_right == elm) { do { (tmp)
= (parent)->ard_entry.rbe_right; if (((parent)->ard_entry
.rbe_right = (tmp)->ard_entry.rbe_left)) { ((tmp)->ard_entry
.rbe_left)->ard_entry.rbe_parent = (parent); } do {} while
(0); if (((tmp)->ard_entry.rbe_parent = (parent)->ard_entry
.rbe_parent)) { if ((parent) == ((parent)->ard_entry.rbe_parent
)->ard_entry.rbe_left) ((parent)->ard_entry.rbe_parent)
->ard_entry.rbe_left = (tmp); else ((parent)->ard_entry
.rbe_parent)->ard_entry.rbe_right = (tmp); } else (head)->
rbh_root = (tmp); (tmp)->ard_entry.rbe_left = (parent); (parent
)->ard_entry.rbe_parent = (tmp); do {} while (0); if (((tmp
)->ard_entry.rbe_parent)) do {} while (0); } while (0); tmp
= parent; parent = elm; elm = tmp; } do { (parent)->ard_entry
.rbe_color = 0; (gparent)->ard_entry.rbe_color = 1; } while
(0); do { (tmp) = (gparent)->ard_entry.rbe_left; if (((gparent
)->ard_entry.rbe_left = (tmp)->ard_entry.rbe_right)) { (
(tmp)->ard_entry.rbe_right)->ard_entry.rbe_parent = (gparent
); } do {} while (0); if (((tmp)->ard_entry.rbe_parent = (
gparent)->ard_entry.rbe_parent)) { if ((gparent) == ((gparent
)->ard_entry.rbe_parent)->ard_entry.rbe_left) ((gparent
)->ard_entry.rbe_parent)->ard_entry.rbe_left = (tmp); else
((gparent)->ard_entry.rbe_parent)->ard_entry.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->ard_entry
.rbe_right = (gparent); (gparent)->ard_entry.rbe_parent = (
tmp); do {} while (0); if (((tmp)->ard_entry.rbe_parent)) do
{} while (0); } while (0); } else { tmp = (gparent)->ard_entry
.rbe_left; if (tmp && (tmp)->ard_entry.rbe_color ==
1) { (tmp)->ard_entry.rbe_color = 0; do { (parent)->ard_entry
.rbe_color = 0; (gparent)->ard_entry.rbe_color = 1; } while
(0); elm = gparent; continue; } if ((parent)->ard_entry.rbe_left
== elm) { do { (tmp) = (parent)->ard_entry.rbe_left; if (
((parent)->ard_entry.rbe_left = (tmp)->ard_entry.rbe_right
)) { ((tmp)->ard_entry.rbe_right)->ard_entry.rbe_parent
= (parent); } do {} while (0); if (((tmp)->ard_entry.rbe_parent
= (parent)->ard_entry.rbe_parent)) { if ((parent) == ((parent
)->ard_entry.rbe_parent)->ard_entry.rbe_left) ((parent)
->ard_entry.rbe_parent)->ard_entry.rbe_left = (tmp); else
((parent)->ard_entry.rbe_parent)->ard_entry.rbe_right =
(tmp); } else (head)->rbh_root = (tmp); (tmp)->ard_entry
.rbe_right = (parent); (parent)->ard_entry.rbe_parent = (tmp
); do {} while (0); if (((tmp)->ard_entry.rbe_parent)) do {
} while (0); } while (0); tmp = parent; parent = elm; elm = tmp
; } do { (parent)->ard_entry.rbe_color = 0; (gparent)->
ard_entry.rbe_color = 1; } while (0); do { (tmp) = (gparent)->
ard_entry.rbe_right; if (((gparent)->ard_entry.rbe_right =
(tmp)->ard_entry.rbe_left)) { ((tmp)->ard_entry.rbe_left
)->ard_entry.rbe_parent = (gparent); } do {} while (0); if
(((tmp)->ard_entry.rbe_parent = (gparent)->ard_entry.rbe_parent
)) { if ((gparent) == ((gparent)->ard_entry.rbe_parent)->
ard_entry.rbe_left) ((gparent)->ard_entry.rbe_parent)->
ard_entry.rbe_left = (tmp); else ((gparent)->ard_entry.rbe_parent
)->ard_entry.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->ard_entry.rbe_left = (gparent); (gparent)
->ard_entry.rbe_parent = (tmp); do {} while (0); if (((tmp
)->ard_entry.rbe_parent)) do {} while (0); } while (0); } }
(head->rbh_root)->ard_entry.rbe_color = 0; } __attribute__
((__unused__)) static void appl_requests_RB_REMOVE_COLOR(struct
appl_requests *head, struct appl_request_downstream *parent,
struct appl_request_downstream *elm) { struct appl_request_downstream
*tmp; while ((elm == ((void *)0) || (elm)->ard_entry.rbe_color
== 0) && elm != (head)->rbh_root) { if ((parent)->
ard_entry.rbe_left == elm) { tmp = (parent)->ard_entry.rbe_right
; if ((tmp)->ard_entry.rbe_color == 1) { do { (tmp)->ard_entry
.rbe_color = 0; (parent)->ard_entry.rbe_color = 1; } while
(0); do { (tmp) = (parent)->ard_entry.rbe_right; if (((parent
)->ard_entry.rbe_right = (tmp)->ard_entry.rbe_left)) { (
(tmp)->ard_entry.rbe_left)->ard_entry.rbe_parent = (parent
); } do {} while (0); if (((tmp)->ard_entry.rbe_parent = (
parent)->ard_entry.rbe_parent)) { if ((parent) == ((parent
)->ard_entry.rbe_parent)->ard_entry.rbe_left) ((parent)
->ard_entry.rbe_parent)->ard_entry.rbe_left = (tmp); else
((parent)->ard_entry.rbe_parent)->ard_entry.rbe_right =
(tmp); } else (head)->rbh_root = (tmp); (tmp)->ard_entry
.rbe_left = (parent); (parent)->ard_entry.rbe_parent = (tmp
); do {} while (0); if (((tmp)->ard_entry.rbe_parent)) do {
} while (0); } while (0); tmp = (parent)->ard_entry.rbe_right
; } if (((tmp)->ard_entry.rbe_left == ((void *)0) || ((tmp
)->ard_entry.rbe_left)->ard_entry.rbe_color == 0) &&
((tmp)->ard_entry.rbe_right == ((void *)0) || ((tmp)->
ard_entry.rbe_right)->ard_entry.rbe_color == 0)) { (tmp)->
ard_entry.rbe_color = 1; elm = parent; parent = (elm)->ard_entry
.rbe_parent; } else { if ((tmp)->ard_entry.rbe_right == ((
void *)0) || ((tmp)->ard_entry.rbe_right)->ard_entry.rbe_color
== 0) { struct appl_request_downstream *oleft; if ((oleft = (
tmp)->ard_entry.rbe_left)) (oleft)->ard_entry.rbe_color
= 0; (tmp)->ard_entry.rbe_color = 1; do { (oleft) = (tmp)
->ard_entry.rbe_left; if (((tmp)->ard_entry.rbe_left = (
oleft)->ard_entry.rbe_right)) { ((oleft)->ard_entry.rbe_right
)->ard_entry.rbe_parent = (tmp); } do {} while (0); if (((
oleft)->ard_entry.rbe_parent = (tmp)->ard_entry.rbe_parent
)) { if ((tmp) == ((tmp)->ard_entry.rbe_parent)->ard_entry
.rbe_left) ((tmp)->ard_entry.rbe_parent)->ard_entry.rbe_left
= (oleft); else ((tmp)->ard_entry.rbe_parent)->ard_entry
.rbe_right = (oleft); } else (head)->rbh_root = (oleft); (
oleft)->ard_entry.rbe_right = (tmp); (tmp)->ard_entry.rbe_parent
= (oleft); do {} while (0); if (((oleft)->ard_entry.rbe_parent
)) do {} while (0); } while (0); tmp = (parent)->ard_entry
.rbe_right; } (tmp)->ard_entry.rbe_color = (parent)->ard_entry
.rbe_color; (parent)->ard_entry.rbe_color = 0; if ((tmp)->
ard_entry.rbe_right) ((tmp)->ard_entry.rbe_right)->ard_entry
.rbe_color = 0; do { (tmp) = (parent)->ard_entry.rbe_right
; if (((parent)->ard_entry.rbe_right = (tmp)->ard_entry
.rbe_left)) { ((tmp)->ard_entry.rbe_left)->ard_entry.rbe_parent
= (parent); } do {} while (0); if (((tmp)->ard_entry.rbe_parent
= (parent)->ard_entry.rbe_parent)) { if ((parent) == ((parent
)->ard_entry.rbe_parent)->ard_entry.rbe_left) ((parent)
->ard_entry.rbe_parent)->ard_entry.rbe_left = (tmp); else
((parent)->ard_entry.rbe_parent)->ard_entry.rbe_right =
(tmp); } else (head)->rbh_root = (tmp); (tmp)->ard_entry
.rbe_left = (parent); (parent)->ard_entry.rbe_parent = (tmp
); do {} while (0); if (((tmp)->ard_entry.rbe_parent)) do {
} while (0); } while (0); elm = (head)->rbh_root; break; }
} else { tmp = (parent)->ard_entry.rbe_left; if ((tmp)->
ard_entry.rbe_color == 1) { do { (tmp)->ard_entry.rbe_color
= 0; (parent)->ard_entry.rbe_color = 1; } while (0); do {
(tmp) = (parent)->ard_entry.rbe_left; if (((parent)->ard_entry
.rbe_left = (tmp)->ard_entry.rbe_right)) { ((tmp)->ard_entry
.rbe_right)->ard_entry.rbe_parent = (parent); } do {} while
(0); if (((tmp)->ard_entry.rbe_parent = (parent)->ard_entry
.rbe_parent)) { if ((parent) == ((parent)->ard_entry.rbe_parent
)->ard_entry.rbe_left) ((parent)->ard_entry.rbe_parent)
->ard_entry.rbe_left = (tmp); else ((parent)->ard_entry
.rbe_parent)->ard_entry.rbe_right = (tmp); } else (head)->
rbh_root = (tmp); (tmp)->ard_entry.rbe_right = (parent); (
parent)->ard_entry.rbe_parent = (tmp); do {} while (0); if
(((tmp)->ard_entry.rbe_parent)) do {} while (0); } while (
0); tmp = (parent)->ard_entry.rbe_left; } if (((tmp)->ard_entry
.rbe_left == ((void *)0) || ((tmp)->ard_entry.rbe_left)->
ard_entry.rbe_color == 0) && ((tmp)->ard_entry.rbe_right
== ((void *)0) || ((tmp)->ard_entry.rbe_right)->ard_entry
.rbe_color == 0)) { (tmp)->ard_entry.rbe_color = 1; elm = parent
; parent = (elm)->ard_entry.rbe_parent; } else { if ((tmp)
->ard_entry.rbe_left == ((void *)0) || ((tmp)->ard_entry
.rbe_left)->ard_entry.rbe_color == 0) { struct appl_request_downstream
*oright; if ((oright = (tmp)->ard_entry.rbe_right)) (oright
)->ard_entry.rbe_color = 0; (tmp)->ard_entry.rbe_color =
1; do { (oright) = (tmp)->ard_entry.rbe_right; if (((tmp)
->ard_entry.rbe_right = (oright)->ard_entry.rbe_left)) {
((oright)->ard_entry.rbe_left)->ard_entry.rbe_parent =
(tmp); } do {} while (0); if (((oright)->ard_entry.rbe_parent
= (tmp)->ard_entry.rbe_parent)) { if ((tmp) == ((tmp)->
ard_entry.rbe_parent)->ard_entry.rbe_left) ((tmp)->ard_entry
.rbe_parent)->ard_entry.rbe_left = (oright); else ((tmp)->
ard_entry.rbe_parent)->ard_entry.rbe_right = (oright); } else
(head)->rbh_root = (oright); (oright)->ard_entry.rbe_left
= (tmp); (tmp)->ard_entry.rbe_parent = (oright); do {} while
(0); if (((oright)->ard_entry.rbe_parent)) do {} while (0
); } while (0); tmp = (parent)->ard_entry.rbe_left; } (tmp
)->ard_entry.rbe_color = (parent)->ard_entry.rbe_color;
(parent)->ard_entry.rbe_color = 0; if ((tmp)->ard_entry
.rbe_left) ((tmp)->ard_entry.rbe_left)->ard_entry.rbe_color
= 0; do { (tmp) = (parent)->ard_entry.rbe_left; if (((parent
)->ard_entry.rbe_left = (tmp)->ard_entry.rbe_right)) { (
(tmp)->ard_entry.rbe_right)->ard_entry.rbe_parent = (parent
); } do {} while (0); if (((tmp)->ard_entry.rbe_parent = (
parent)->ard_entry.rbe_parent)) { if ((parent) == ((parent
)->ard_entry.rbe_parent)->ard_entry.rbe_left) ((parent)
->ard_entry.rbe_parent)->ard_entry.rbe_left = (tmp); else
((parent)->ard_entry.rbe_parent)->ard_entry.rbe_right =
(tmp); } else (head)->rbh_root = (tmp); (tmp)->ard_entry
.rbe_right = (parent); (parent)->ard_entry.rbe_parent = (tmp
); do {} while (0); if (((tmp)->ard_entry.rbe_parent)) do {
} while (0); } while (0); elm = (head)->rbh_root; break; }
} } if (elm) (elm)->ard_entry.rbe_color = 0; } __attribute__
((__unused__)) static struct appl_request_downstream * appl_requests_RB_REMOVE
(struct appl_requests *head, struct appl_request_downstream *
elm) { struct appl_request_downstream *child, *parent, *old =
elm; int color; if ((elm)->ard_entry.rbe_left == ((void *
)0)) child = (elm)->ard_entry.rbe_right; else if ((elm)->
ard_entry.rbe_right == ((void *)0)) child = (elm)->ard_entry
.rbe_left; else { struct appl_request_downstream *left; elm =
(elm)->ard_entry.rbe_right; while ((left = (elm)->ard_entry
.rbe_left)) elm = left; child = (elm)->ard_entry.rbe_right
; parent = (elm)->ard_entry.rbe_parent; color = (elm)->
ard_entry.rbe_color; if (child) (child)->ard_entry.rbe_parent
= parent; if (parent) { if ((parent)->ard_entry.rbe_left ==
elm) (parent)->ard_entry.rbe_left = child; else (parent)->
ard_entry.rbe_right = child; do {} while (0); } else (head)->
rbh_root = child; if ((elm)->ard_entry.rbe_parent == old) parent
= elm; (elm)->ard_entry = (old)->ard_entry; if ((old)->
ard_entry.rbe_parent) { if (((old)->ard_entry.rbe_parent)->
ard_entry.rbe_left == old) ((old)->ard_entry.rbe_parent)->
ard_entry.rbe_left = elm; else ((old)->ard_entry.rbe_parent
)->ard_entry.rbe_right = elm; do {} while (0); } else (head
)->rbh_root = elm; ((old)->ard_entry.rbe_left)->ard_entry
.rbe_parent = elm; if ((old)->ard_entry.rbe_right) ((old)->
ard_entry.rbe_right)->ard_entry.rbe_parent = elm; if (parent
) { left = parent; do { do {} while (0); } while ((left = (left
)->ard_entry.rbe_parent)); } goto color; } parent = (elm)->
ard_entry.rbe_parent; color = (elm)->ard_entry.rbe_color; if
(child) (child)->ard_entry.rbe_parent = parent; if (parent
) { if ((parent)->ard_entry.rbe_left == elm) (parent)->
ard_entry.rbe_left = child; else (parent)->ard_entry.rbe_right
= child; do {} while (0); } else (head)->rbh_root = child
; color: if (color == 0) appl_requests_RB_REMOVE_COLOR(head, parent
, child); return (old); } __attribute__((__unused__)) static struct
appl_request_downstream * appl_requests_RB_INSERT(struct appl_requests
*head, struct appl_request_downstream *elm) { struct appl_request_downstream
*tmp; struct appl_request_downstream *parent = ((void *)0); int
comp = 0; tmp = (head)->rbh_root; while (tmp) { parent = tmp
; comp = (appl_request_cmp)(elm, parent); if (comp < 0) tmp
= (tmp)->ard_entry.rbe_left; else if (comp > 0) tmp = (
tmp)->ard_entry.rbe_right; else return (tmp); } do { (elm)
->ard_entry.rbe_parent = parent; (elm)->ard_entry.rbe_left
= (elm)->ard_entry.rbe_right = ((void *)0); (elm)->ard_entry
.rbe_color = 1; } while (0); if (parent != ((void *)0)) { if (
comp < 0) (parent)->ard_entry.rbe_left = elm; else (parent
)->ard_entry.rbe_right = elm; do {} while (0); } else (head
)->rbh_root = elm; appl_requests_RB_INSERT_COLOR(head, elm
); return (((void *)0)); } __attribute__((__unused__)) static
struct appl_request_downstream * appl_requests_RB_FIND(struct
appl_requests *head, struct appl_request_downstream *elm) { struct
appl_request_downstream *tmp = (head)->rbh_root; int comp
; while (tmp) { comp = appl_request_cmp(elm, tmp); if (comp <
0) tmp = (tmp)->ard_entry.rbe_left; else if (comp > 0)
tmp = (tmp)->ard_entry.rbe_right; else return (tmp); } return
(((void *)0)); } __attribute__((__unused__)) static struct appl_request_downstream
* appl_requests_RB_NFIND(struct appl_requests *head, struct appl_request_downstream
*elm) { struct appl_request_downstream *tmp = (head)->rbh_root
; struct appl_request_downstream *res = ((void *)0); int comp
; while (tmp) { comp = appl_request_cmp(elm, tmp); if (comp <
0) { res = tmp; tmp = (tmp)->ard_entry.rbe_left; } else if
(comp > 0) tmp = (tmp)->ard_entry.rbe_right; else return
(tmp); } return (res); } __attribute__((__unused__)) static struct
appl_request_downstream * appl_requests_RB_NEXT(struct appl_request_downstream
*elm) { if ((elm)->ard_entry.rbe_right) { elm = (elm)->
ard_entry.rbe_right; while ((elm)->ard_entry.rbe_left) elm
= (elm)->ard_entry.rbe_left; } else { if ((elm)->ard_entry
.rbe_parent && (elm == ((elm)->ard_entry.rbe_parent
)->ard_entry.rbe_left)) elm = (elm)->ard_entry.rbe_parent
; else { while ((elm)->ard_entry.rbe_parent && (elm
== ((elm)->ard_entry.rbe_parent)->ard_entry.rbe_right)
) elm = (elm)->ard_entry.rbe_parent; elm = (elm)->ard_entry
.rbe_parent; } } return (elm); } __attribute__((__unused__)) static
struct appl_request_downstream * appl_requests_RB_PREV(struct
appl_request_downstream *elm) { if ((elm)->ard_entry.rbe_left
) { elm = (elm)->ard_entry.rbe_left; while ((elm)->ard_entry
.rbe_right) elm = (elm)->ard_entry.rbe_right; } else { if (
(elm)->ard_entry.rbe_parent && (elm == ((elm)->
ard_entry.rbe_parent)->ard_entry.rbe_right)) elm = (elm)->
ard_entry.rbe_parent; else { while ((elm)->ard_entry.rbe_parent
&& (elm == ((elm)->ard_entry.rbe_parent)->ard_entry
.rbe_left)) elm = (elm)->ard_entry.rbe_parent; elm = (elm)
->ard_entry.rbe_parent; } } return (elm); } __attribute__(
(__unused__)) static struct appl_request_downstream * appl_requests_RB_MINMAX
(struct appl_requests *head, int val) { struct appl_request_downstream
*tmp = (head)->rbh_root; struct appl_request_downstream *
parent = ((void *)0); while (tmp) { parent = tmp; if (val <
0) tmp = (tmp)->ard_entry.rbe_left; else tmp = (tmp)->
ard_entry.rbe_right; } return (parent); }
1813 appl_request_cmp)__attribute__((__unused__)) static void appl_requests_RB_INSERT_COLOR
(struct appl_requests *head, struct appl_request_downstream *
elm) { struct appl_request_downstream *parent, *gparent, *tmp
; while ((parent = (elm)->ard_entry.rbe_parent) &&
(parent)->ard_entry.rbe_color == 1) { gparent = (parent)->
ard_entry.rbe_parent; if (parent == (gparent)->ard_entry.rbe_left
) { tmp = (gparent)->ard_entry.rbe_right; if (tmp &&
(tmp)->ard_entry.rbe_color == 1) { (tmp)->ard_entry.rbe_color
= 0; do { (parent)->ard_entry.rbe_color = 0; (gparent)->
ard_entry.rbe_color = 1; } while (0); elm = gparent; continue
; } if ((parent)->ard_entry.rbe_right == elm) { do { (tmp)
= (parent)->ard_entry.rbe_right; if (((parent)->ard_entry
.rbe_right = (tmp)->ard_entry.rbe_left)) { ((tmp)->ard_entry
.rbe_left)->ard_entry.rbe_parent = (parent); } do {} while
(0); if (((tmp)->ard_entry.rbe_parent = (parent)->ard_entry
.rbe_parent)) { if ((parent) == ((parent)->ard_entry.rbe_parent
)->ard_entry.rbe_left) ((parent)->ard_entry.rbe_parent)
->ard_entry.rbe_left = (tmp); else ((parent)->ard_entry
.rbe_parent)->ard_entry.rbe_right = (tmp); } else (head)->
rbh_root = (tmp); (tmp)->ard_entry.rbe_left = (parent); (parent
)->ard_entry.rbe_parent = (tmp); do {} while (0); if (((tmp
)->ard_entry.rbe_parent)) do {} while (0); } while (0); tmp
= parent; parent = elm; elm = tmp; } do { (parent)->ard_entry
.rbe_color = 0; (gparent)->ard_entry.rbe_color = 1; } while
(0); do { (tmp) = (gparent)->ard_entry.rbe_left; if (((gparent
)->ard_entry.rbe_left = (tmp)->ard_entry.rbe_right)) { (
(tmp)->ard_entry.rbe_right)->ard_entry.rbe_parent = (gparent
); } do {} while (0); if (((tmp)->ard_entry.rbe_parent = (
gparent)->ard_entry.rbe_parent)) { if ((gparent) == ((gparent
)->ard_entry.rbe_parent)->ard_entry.rbe_left) ((gparent
)->ard_entry.rbe_parent)->ard_entry.rbe_left = (tmp); else
((gparent)->ard_entry.rbe_parent)->ard_entry.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->ard_entry
.rbe_right = (gparent); (gparent)->ard_entry.rbe_parent = (
tmp); do {} while (0); if (((tmp)->ard_entry.rbe_parent)) do
{} while (0); } while (0); } else { tmp = (gparent)->ard_entry
.rbe_left; if (tmp && (tmp)->ard_entry.rbe_color ==
1) { (tmp)->ard_entry.rbe_color = 0; do { (parent)->ard_entry
.rbe_color = 0; (gparent)->ard_entry.rbe_color = 1; } while
(0); elm = gparent; continue; } if ((parent)->ard_entry.rbe_left
== elm) { do { (tmp) = (parent)->ard_entry.rbe_left; if (
((parent)->ard_entry.rbe_left = (tmp)->ard_entry.rbe_right
)) { ((tmp)->ard_entry.rbe_right)->ard_entry.rbe_parent
= (parent); } do {} while (0); if (((tmp)->ard_entry.rbe_parent
= (parent)->ard_entry.rbe_parent)) { if ((parent) == ((parent
)->ard_entry.rbe_parent)->ard_entry.rbe_left) ((parent)
->ard_entry.rbe_parent)->ard_entry.rbe_left = (tmp); else
((parent)->ard_entry.rbe_parent)->ard_entry.rbe_right =
(tmp); } else (head)->rbh_root = (tmp); (tmp)->ard_entry
.rbe_right = (parent); (parent)->ard_entry.rbe_parent = (tmp
); do {} while (0); if (((tmp)->ard_entry.rbe_parent)) do {
} while (0); } while (0); tmp = parent; parent = elm; elm = tmp
; } do { (parent)->ard_entry.rbe_color = 0; (gparent)->
ard_entry.rbe_color = 1; } while (0); do { (tmp) = (gparent)->
ard_entry.rbe_right; if (((gparent)->ard_entry.rbe_right =
(tmp)->ard_entry.rbe_left)) { ((tmp)->ard_entry.rbe_left
)->ard_entry.rbe_parent = (gparent); } do {} while (0); if
(((tmp)->ard_entry.rbe_parent = (gparent)->ard_entry.rbe_parent
)) { if ((gparent) == ((gparent)->ard_entry.rbe_parent)->
ard_entry.rbe_left) ((gparent)->ard_entry.rbe_parent)->
ard_entry.rbe_left = (tmp); else ((gparent)->ard_entry.rbe_parent
)->ard_entry.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->ard_entry.rbe_left = (gparent); (gparent)
->ard_entry.rbe_parent = (tmp); do {} while (0); if (((tmp
)->ard_entry.rbe_parent)) do {} while (0); } while (0); } }
(head->rbh_root)->ard_entry.rbe_color = 0; } __attribute__
((__unused__)) static void appl_requests_RB_REMOVE_COLOR(struct
appl_requests *head, struct appl_request_downstream *parent,
struct appl_request_downstream *elm) { struct appl_request_downstream
*tmp; while ((elm == ((void *)0) || (elm)->ard_entry.rbe_color
== 0) && elm != (head)->rbh_root) { if ((parent)->
ard_entry.rbe_left == elm) { tmp = (parent)->ard_entry.rbe_right
; if ((tmp)->ard_entry.rbe_color == 1) { do { (tmp)->ard_entry
.rbe_color = 0; (parent)->ard_entry.rbe_color = 1; } while
(0); do { (tmp) = (parent)->ard_entry.rbe_right; if (((parent
)->ard_entry.rbe_right = (tmp)->ard_entry.rbe_left)) { (
(tmp)->ard_entry.rbe_left)->ard_entry.rbe_parent = (parent
); } do {} while (0); if (((tmp)->ard_entry.rbe_parent = (
parent)->ard_entry.rbe_parent)) { if ((parent) == ((parent
)->ard_entry.rbe_parent)->ard_entry.rbe_left) ((parent)
->ard_entry.rbe_parent)->ard_entry.rbe_left = (tmp); else
((parent)->ard_entry.rbe_parent)->ard_entry.rbe_right =
(tmp); } else (head)->rbh_root = (tmp); (tmp)->ard_entry
.rbe_left = (parent); (parent)->ard_entry.rbe_parent = (tmp
); do {} while (0); if (((tmp)->ard_entry.rbe_parent)) do {
} while (0); } while (0); tmp = (parent)->ard_entry.rbe_right
; } if (((tmp)->ard_entry.rbe_left == ((void *)0) || ((tmp
)->ard_entry.rbe_left)->ard_entry.rbe_color == 0) &&
((tmp)->ard_entry.rbe_right == ((void *)0) || ((tmp)->
ard_entry.rbe_right)->ard_entry.rbe_color == 0)) { (tmp)->
ard_entry.rbe_color = 1; elm = parent; parent = (elm)->ard_entry
.rbe_parent; } else { if ((tmp)->ard_entry.rbe_right == ((
void *)0) || ((tmp)->ard_entry.rbe_right)->ard_entry.rbe_color
== 0) { struct appl_request_downstream *oleft; if ((oleft = (
tmp)->ard_entry.rbe_left)) (oleft)->ard_entry.rbe_color
= 0; (tmp)->ard_entry.rbe_color = 1; do { (oleft) = (tmp)
->ard_entry.rbe_left; if (((tmp)->ard_entry.rbe_left = (
oleft)->ard_entry.rbe_right)) { ((oleft)->ard_entry.rbe_right
)->ard_entry.rbe_parent = (tmp); } do {} while (0); if (((
oleft)->ard_entry.rbe_parent = (tmp)->ard_entry.rbe_parent
)) { if ((tmp) == ((tmp)->ard_entry.rbe_parent)->ard_entry
.rbe_left) ((tmp)->ard_entry.rbe_parent)->ard_entry.rbe_left
= (oleft); else ((tmp)->ard_entry.rbe_parent)->ard_entry
.rbe_right = (oleft); } else (head)->rbh_root = (oleft); (
oleft)->ard_entry.rbe_right = (tmp); (tmp)->ard_entry.rbe_parent
= (oleft); do {} while (0); if (((oleft)->ard_entry.rbe_parent
)) do {} while (0); } while (0); tmp = (parent)->ard_entry
.rbe_right; } (tmp)->ard_entry.rbe_color = (parent)->ard_entry
.rbe_color; (parent)->ard_entry.rbe_color = 0; if ((tmp)->
ard_entry.rbe_right) ((tmp)->ard_entry.rbe_right)->ard_entry
.rbe_color = 0; do { (tmp) = (parent)->ard_entry.rbe_right
; if (((parent)->ard_entry.rbe_right = (tmp)->ard_entry
.rbe_left)) { ((tmp)->ard_entry.rbe_left)->ard_entry.rbe_parent
= (parent); } do {} while (0); if (((tmp)->ard_entry.rbe_parent
= (parent)->ard_entry.rbe_parent)) { if ((parent) == ((parent
)->ard_entry.rbe_parent)->ard_entry.rbe_left) ((parent)
->ard_entry.rbe_parent)->ard_entry.rbe_left = (tmp); else
((parent)->ard_entry.rbe_parent)->ard_entry.rbe_right =
(tmp); } else (head)->rbh_root = (tmp); (tmp)->ard_entry
.rbe_left = (parent); (parent)->ard_entry.rbe_parent = (tmp
); do {} while (0); if (((tmp)->ard_entry.rbe_parent)) do {
} while (0); } while (0); elm = (head)->rbh_root; break; }
} else { tmp = (parent)->ard_entry.rbe_left; if ((tmp)->
ard_entry.rbe_color == 1) { do { (tmp)->ard_entry.rbe_color
= 0; (parent)->ard_entry.rbe_color = 1; } while (0); do {
(tmp) = (parent)->ard_entry.rbe_left; if (((parent)->ard_entry
.rbe_left = (tmp)->ard_entry.rbe_right)) { ((tmp)->ard_entry
.rbe_right)->ard_entry.rbe_parent = (parent); } do {} while
(0); if (((tmp)->ard_entry.rbe_parent = (parent)->ard_entry
.rbe_parent)) { if ((parent) == ((parent)->ard_entry.rbe_parent
)->ard_entry.rbe_left) ((parent)->ard_entry.rbe_parent)
->ard_entry.rbe_left = (tmp); else ((parent)->ard_entry
.rbe_parent)->ard_entry.rbe_right = (tmp); } else (head)->
rbh_root = (tmp); (tmp)->ard_entry.rbe_right = (parent); (
parent)->ard_entry.rbe_parent = (tmp); do {} while (0); if
(((tmp)->ard_entry.rbe_parent)) do {} while (0); } while (
0); tmp = (parent)->ard_entry.rbe_left; } if (((tmp)->ard_entry
.rbe_left == ((void *)0) || ((tmp)->ard_entry.rbe_left)->
ard_entry.rbe_color == 0) && ((tmp)->ard_entry.rbe_right
== ((void *)0) || ((tmp)->ard_entry.rbe_right)->ard_entry
.rbe_color == 0)) { (tmp)->ard_entry.rbe_color = 1; elm = parent
; parent = (elm)->ard_entry.rbe_parent; } else { if ((tmp)
->ard_entry.rbe_left == ((void *)0) || ((tmp)->ard_entry
.rbe_left)->ard_entry.rbe_color == 0) { struct appl_request_downstream
*oright; if ((oright = (tmp)->ard_entry.rbe_right)) (oright
)->ard_entry.rbe_color = 0; (tmp)->ard_entry.rbe_color =
1; do { (oright) = (tmp)->ard_entry.rbe_right; if (((tmp)
->ard_entry.rbe_right = (oright)->ard_entry.rbe_left)) {
((oright)->ard_entry.rbe_left)->ard_entry.rbe_parent =
(tmp); } do {} while (0); if (((oright)->ard_entry.rbe_parent
= (tmp)->ard_entry.rbe_parent)) { if ((tmp) == ((tmp)->
ard_entry.rbe_parent)->ard_entry.rbe_left) ((tmp)->ard_entry
.rbe_parent)->ard_entry.rbe_left = (oright); else ((tmp)->
ard_entry.rbe_parent)->ard_entry.rbe_right = (oright); } else
(head)->rbh_root = (oright); (oright)->ard_entry.rbe_left
= (tmp); (tmp)->ard_entry.rbe_parent = (oright); do {} while
(0); if (((oright)->ard_entry.rbe_parent)) do {} while (0
); } while (0); tmp = (parent)->ard_entry.rbe_left; } (tmp
)->ard_entry.rbe_color = (parent)->ard_entry.rbe_color;
(parent)->ard_entry.rbe_color = 0; if ((tmp)->ard_entry
.rbe_left) ((tmp)->ard_entry.rbe_left)->ard_entry.rbe_color
= 0; do { (tmp) = (parent)->ard_entry.rbe_left; if (((parent
)->ard_entry.rbe_left = (tmp)->ard_entry.rbe_right)) { (
(tmp)->ard_entry.rbe_right)->ard_entry.rbe_parent = (parent
); } do {} while (0); if (((tmp)->ard_entry.rbe_parent = (
parent)->ard_entry.rbe_parent)) { if ((parent) == ((parent
)->ard_entry.rbe_parent)->ard_entry.rbe_left) ((parent)
->ard_entry.rbe_parent)->ard_entry.rbe_left = (tmp); else
((parent)->ard_entry.rbe_parent)->ard_entry.rbe_right =
(tmp); } else (head)->rbh_root = (tmp); (tmp)->ard_entry
.rbe_right = (parent); (parent)->ard_entry.rbe_parent = (tmp
); do {} while (0); if (((tmp)->ard_entry.rbe_parent)) do {
} while (0); } while (0); elm = (head)->rbh_root; break; }
} } if (elm) (elm)->ard_entry.rbe_color = 0; } __attribute__
((__unused__)) static struct appl_request_downstream * appl_requests_RB_REMOVE
(struct appl_requests *head, struct appl_request_downstream *
elm) { struct appl_request_downstream *child, *parent, *old =
elm; int color; if ((elm)->ard_entry.rbe_left == ((void *
)0)) child = (elm)->ard_entry.rbe_right; else if ((elm)->
ard_entry.rbe_right == ((void *)0)) child = (elm)->ard_entry
.rbe_left; else { struct appl_request_downstream *left; elm =
(elm)->ard_entry.rbe_right; while ((left = (elm)->ard_entry
.rbe_left)) elm = left; child = (elm)->ard_entry.rbe_right
; parent = (elm)->ard_entry.rbe_parent; color = (elm)->
ard_entry.rbe_color; if (child) (child)->ard_entry.rbe_parent
= parent; if (parent) { if ((parent)->ard_entry.rbe_left ==
elm) (parent)->ard_entry.rbe_left = child; else (parent)->
ard_entry.rbe_right = child; do {} while (0); } else (head)->
rbh_root = child; if ((elm)->ard_entry.rbe_parent == old) parent
= elm; (elm)->ard_entry = (old)->ard_entry; if ((old)->
ard_entry.rbe_parent) { if (((old)->ard_entry.rbe_parent)->
ard_entry.rbe_left == old) ((old)->ard_entry.rbe_parent)->
ard_entry.rbe_left = elm; else ((old)->ard_entry.rbe_parent
)->ard_entry.rbe_right = elm; do {} while (0); } else (head
)->rbh_root = elm; ((old)->ard_entry.rbe_left)->ard_entry
.rbe_parent = elm; if ((old)->ard_entry.rbe_right) ((old)->
ard_entry.rbe_right)->ard_entry.rbe_parent = elm; if (parent
) { left = parent; do { do {} while (0); } while ((left = (left
)->ard_entry.rbe_parent)); } goto color; } parent = (elm)->
ard_entry.rbe_parent; color = (elm)->ard_entry.rbe_color; if
(child) (child)->ard_entry.rbe_parent = parent; if (parent
) { if ((parent)->ard_entry.rbe_left == elm) (parent)->
ard_entry.rbe_left = child; else (parent)->ard_entry.rbe_right
= child; do {} while (0); } else (head)->rbh_root = child
; color: if (color == 0) appl_requests_RB_REMOVE_COLOR(head, parent
, child); return (old); } __attribute__((__unused__)) static struct
appl_request_downstream * appl_requests_RB_INSERT(struct appl_requests
*head, struct appl_request_downstream *elm) { struct appl_request_downstream
*tmp; struct appl_request_downstream *parent = ((void *)0); int
comp = 0; tmp = (head)->rbh_root; while (tmp) { parent = tmp
; comp = (appl_request_cmp)(elm, parent); if (comp < 0) tmp
= (tmp)->ard_entry.rbe_left; else if (comp > 0) tmp = (
tmp)->ard_entry.rbe_right; else return (tmp); } do { (elm)
->ard_entry.rbe_parent = parent; (elm)->ard_entry.rbe_left
= (elm)->ard_entry.rbe_right = ((void *)0); (elm)->ard_entry
.rbe_color = 1; } while (0); if (parent != ((void *)0)) { if (
comp < 0) (parent)->ard_entry.rbe_left = elm; else (parent
)->ard_entry.rbe_right = elm; do {} while (0); } else (head
)->rbh_root = elm; appl_requests_RB_INSERT_COLOR(head, elm
); return (((void *)0)); } __attribute__((__unused__)) static
struct appl_request_downstream * appl_requests_RB_FIND(struct
appl_requests *head, struct appl_request_downstream *elm) { struct
appl_request_downstream *tmp = (head)->rbh_root; int comp
; while (tmp) { comp = appl_request_cmp(elm, tmp); if (comp <
0) tmp = (tmp)->ard_entry.rbe_left; else if (comp > 0)
tmp = (tmp)->ard_entry.rbe_right; else return (tmp); } return
(((void *)0)); } __attribute__((__unused__)) static struct appl_request_downstream
* appl_requests_RB_NFIND(struct appl_requests *head, struct appl_request_downstream
*elm) { struct appl_request_downstream *tmp = (head)->rbh_root
; struct appl_request_downstream *res = ((void *)0); int comp
; while (tmp) { comp = appl_request_cmp(elm, tmp); if (comp <
0) { res = tmp; tmp = (tmp)->ard_entry.rbe_left; } else if
(comp > 0) tmp = (tmp)->ard_entry.rbe_right; else return
(tmp); } return (res); } __attribute__((__unused__)) static struct
appl_request_downstream * appl_requests_RB_NEXT(struct appl_request_downstream
*elm) { if ((elm)->ard_entry.rbe_right) { elm = (elm)->
ard_entry.rbe_right; while ((elm)->ard_entry.rbe_left) elm
= (elm)->ard_entry.rbe_left; } else { if ((elm)->ard_entry
.rbe_parent && (elm == ((elm)->ard_entry.rbe_parent
)->ard_entry.rbe_left)) elm = (elm)->ard_entry.rbe_parent
; else { while ((elm)->ard_entry.rbe_parent && (elm
== ((elm)->ard_entry.rbe_parent)->ard_entry.rbe_right)
) elm = (elm)->ard_entry.rbe_parent; elm = (elm)->ard_entry
.rbe_parent; } } return (elm); } __attribute__((__unused__)) static
struct appl_request_downstream * appl_requests_RB_PREV(struct
appl_request_downstream *elm) { if ((elm)->ard_entry.rbe_left
) { elm = (elm)->ard_entry.rbe_left; while ((elm)->ard_entry
.rbe_right) elm = (elm)->ard_entry.rbe_right; } else { if (
(elm)->ard_entry.rbe_parent && (elm == ((elm)->
ard_entry.rbe_parent)->ard_entry.rbe_right)) elm = (elm)->
ard_entry.rbe_parent; else { while ((elm)->ard_entry.rbe_parent
&& (elm == ((elm)->ard_entry.rbe_parent)->ard_entry
.rbe_left)) elm = (elm)->ard_entry.rbe_parent; elm = (elm)
->ard_entry.rbe_parent; } } return (elm); } __attribute__(
(__unused__)) static struct appl_request_downstream * appl_requests_RB_MINMAX
(struct appl_requests *head, int val) { struct appl_request_downstream
*tmp = (head)->rbh_root; struct appl_request_downstream *
parent = ((void *)0); while (tmp) { parent = tmp; if (val <
0) tmp = (tmp)->ard_entry.rbe_left; else tmp = (tmp)->
ard_entry.rbe_right; } return (parent); }
;