File: | src/usr.sbin/snmpd/application_agentx.c |
Warning: | line 262, column 4 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: application_agentx.c,v 1.15 2023/12/21 12:43:30 martijn Exp $ */ | |||
2 | /* | |||
3 | * Copyright (c) 2022 Martijn van Duren <martijn@openbsd.org> | |||
4 | * | |||
5 | * Permission to use, copy, modify, and distribute this software for any | |||
6 | * purpose with or without fee is hereby granted, provided that the above | |||
7 | * copyright notice and this permission notice appear in all copies. | |||
8 | * | |||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
16 | */ | |||
17 | ||||
18 | #include <sys/queue.h> | |||
19 | #include <sys/socket.h> | |||
20 | #include <sys/stat.h> | |||
21 | #include <sys/tree.h> | |||
22 | #include <sys/un.h> | |||
23 | ||||
24 | #include <ber.h> | |||
25 | #include <errno(*__errno()).h> | |||
26 | #include <event.h> | |||
27 | #include <inttypes.h> | |||
28 | #include <stdint.h> | |||
29 | #include <stdio.h> | |||
30 | #include <stdlib.h> | |||
31 | #include <string.h> | |||
32 | #include <unistd.h> | |||
33 | ||||
34 | #include "application.h" | |||
35 | #include "ax.h" | |||
36 | #include "log.h" | |||
37 | #include "smi.h" | |||
38 | #include "snmp.h" | |||
39 | #include "snmpd.h" | |||
40 | ||||
41 | #define AGENTX_DEFAULTTIMEOUT5 5 | |||
42 | ||||
43 | struct appl_agentx_connection { | |||
44 | uint32_t conn_id; | |||
45 | /* | |||
46 | * A backend has several overruling properties: | |||
47 | * - If it exits, snmpd crashes | |||
48 | * - All registrations are priority 1 | |||
49 | * - All registrations own the subtree. | |||
50 | */ | |||
51 | int conn_backend; | |||
52 | struct ax *conn_ax; | |||
53 | struct event conn_rev; | |||
54 | struct event conn_wev; | |||
55 | ||||
56 | TAILQ_HEAD(, appl_agentx_session)struct { struct appl_agentx_session *tqh_first; struct appl_agentx_session **tqh_last; } conn_sessions; | |||
57 | RB_ENTRY(appl_agentx_connection)struct { struct appl_agentx_connection *rbe_left; struct appl_agentx_connection *rbe_right; struct appl_agentx_connection *rbe_parent; int rbe_color ; } conn_entry; | |||
58 | }; | |||
59 | ||||
60 | struct appl_agentx_session { | |||
61 | uint32_t sess_id; | |||
62 | struct appl_agentx_connection *sess_conn; | |||
63 | /* | |||
64 | * RFC 2741 section 7.1.1: | |||
65 | * All subsequent AgentX protocol operations initiated by the master | |||
66 | * agent for this session must use this byte ordering and set this bit | |||
67 | * accordingly. | |||
68 | */ | |||
69 | enum ax_byte_order sess_byteorder; | |||
70 | uint8_t sess_timeout; | |||
71 | struct ax_oid sess_oid; | |||
72 | struct ax_ostring sess_descr; | |||
73 | struct appl_backend sess_backend; | |||
74 | ||||
75 | RB_ENTRY(appl_agentx_session)struct { struct appl_agentx_session *rbe_left; struct appl_agentx_session *rbe_right; struct appl_agentx_session *rbe_parent; int rbe_color ; } sess_entry; | |||
76 | TAILQ_ENTRY(appl_agentx_session)struct { struct appl_agentx_session *tqe_next; struct appl_agentx_session **tqe_prev; } sess_conn_entry; | |||
77 | }; | |||
78 | ||||
79 | void appl_agentx_listen(struct agentx_master *); | |||
80 | void appl_agentx_accept(int, short, void *); | |||
81 | void appl_agentx_free(struct appl_agentx_connection *, enum appl_close_reason); | |||
82 | void appl_agentx_recv(int, short, void *); | |||
83 | void appl_agentx_open(struct appl_agentx_connection *, struct ax_pdu *); | |||
84 | void appl_agentx_close(struct appl_agentx_session *, struct ax_pdu *); | |||
85 | void appl_agentx_forceclose(struct appl_backend *, enum appl_close_reason); | |||
86 | void appl_agentx_session_free(struct appl_agentx_session *); | |||
87 | void appl_agentx_register(struct appl_agentx_session *, struct ax_pdu *); | |||
88 | void appl_agentx_unregister(struct appl_agentx_session *, struct ax_pdu *); | |||
89 | void appl_agentx_get(struct appl_backend *, int32_t, int32_t, const char *, | |||
90 | struct appl_varbind *); | |||
91 | void appl_agentx_getnext(struct appl_backend *, int32_t, int32_t, const char *, | |||
92 | struct appl_varbind *); | |||
93 | void appl_agentx_addagentcaps(struct appl_agentx_session *, struct ax_pdu *); | |||
94 | void appl_agentx_removeagentcaps(struct appl_agentx_session *, struct ax_pdu *); | |||
95 | void appl_agentx_response(struct appl_agentx_session *, struct ax_pdu *); | |||
96 | void appl_agentx_send(int, short, void *); | |||
97 | struct ber_oid *appl_agentx_oid2ber_oid(struct ax_oid *, struct ber_oid *); | |||
98 | struct ber_element *appl_agentx_value2ber_element(struct ax_varbind *); | |||
99 | struct ax_ostring *appl_agentx_string2ostring(const char *, | |||
100 | struct ax_ostring *); | |||
101 | int appl_agentx_cmp(struct appl_agentx_connection *, | |||
102 | struct appl_agentx_connection *); | |||
103 | int appl_agentx_session_cmp(struct appl_agentx_session *, | |||
104 | struct appl_agentx_session *); | |||
105 | ||||
106 | struct appl_backend_functions appl_agentx_functions = { | |||
107 | .ab_close = appl_agentx_forceclose, | |||
108 | .ab_get = appl_agentx_get, | |||
109 | .ab_getnext = appl_agentx_getnext, | |||
110 | .ab_getbulk = NULL((void *)0), /* not properly supported in application.c and libagentx */ | |||
111 | }; | |||
112 | ||||
113 | RB_HEAD(appl_agentx_conns, appl_agentx_connection)struct appl_agentx_conns { struct appl_agentx_connection *rbh_root ; } appl_agentx_conns = | |||
114 | RB_INITIALIZER(&appl_agentx_conns){ ((void *)0) }; | |||
115 | RB_HEAD(appl_agentx_sessions, appl_agentx_session)struct appl_agentx_sessions { struct appl_agentx_session *rbh_root ; } appl_agentx_sessions = | |||
116 | RB_INITIALIZER(&appl_agentx_sessions){ ((void *)0) }; | |||
117 | ||||
118 | RB_PROTOTYPE_STATIC(appl_agentx_conns, appl_agentx_connection, conn_entry,__attribute__((__unused__)) static void appl_agentx_conns_RB_INSERT_COLOR (struct appl_agentx_conns *, struct appl_agentx_connection *) ; __attribute__((__unused__)) static void appl_agentx_conns_RB_REMOVE_COLOR (struct appl_agentx_conns *, struct appl_agentx_connection *, struct appl_agentx_connection *);__attribute__((__unused__)) static struct appl_agentx_connection *appl_agentx_conns_RB_REMOVE (struct appl_agentx_conns *, struct appl_agentx_connection *) ; __attribute__((__unused__)) static struct appl_agentx_connection *appl_agentx_conns_RB_INSERT(struct appl_agentx_conns *, struct appl_agentx_connection *); __attribute__((__unused__)) static struct appl_agentx_connection *appl_agentx_conns_RB_FIND(struct appl_agentx_conns *, struct appl_agentx_connection *); __attribute__ ((__unused__)) static struct appl_agentx_connection *appl_agentx_conns_RB_NFIND (struct appl_agentx_conns *, struct appl_agentx_connection *) ; __attribute__((__unused__)) static struct appl_agentx_connection *appl_agentx_conns_RB_NEXT(struct appl_agentx_connection *); __attribute__((__unused__)) static struct appl_agentx_connection *appl_agentx_conns_RB_PREV(struct appl_agentx_connection *); __attribute__((__unused__)) static struct appl_agentx_connection *appl_agentx_conns_RB_MINMAX(struct appl_agentx_conns *, int ); | |||
119 | appl_agentx_cmp)__attribute__((__unused__)) static void appl_agentx_conns_RB_INSERT_COLOR (struct appl_agentx_conns *, struct appl_agentx_connection *) ; __attribute__((__unused__)) static void appl_agentx_conns_RB_REMOVE_COLOR (struct appl_agentx_conns *, struct appl_agentx_connection *, struct appl_agentx_connection *);__attribute__((__unused__)) static struct appl_agentx_connection *appl_agentx_conns_RB_REMOVE (struct appl_agentx_conns *, struct appl_agentx_connection *) ; __attribute__((__unused__)) static struct appl_agentx_connection *appl_agentx_conns_RB_INSERT(struct appl_agentx_conns *, struct appl_agentx_connection *); __attribute__((__unused__)) static struct appl_agentx_connection *appl_agentx_conns_RB_FIND(struct appl_agentx_conns *, struct appl_agentx_connection *); __attribute__ ((__unused__)) static struct appl_agentx_connection *appl_agentx_conns_RB_NFIND (struct appl_agentx_conns *, struct appl_agentx_connection *) ; __attribute__((__unused__)) static struct appl_agentx_connection *appl_agentx_conns_RB_NEXT(struct appl_agentx_connection *); __attribute__((__unused__)) static struct appl_agentx_connection *appl_agentx_conns_RB_PREV(struct appl_agentx_connection *); __attribute__((__unused__)) static struct appl_agentx_connection *appl_agentx_conns_RB_MINMAX(struct appl_agentx_conns *, int );; | |||
120 | RB_PROTOTYPE_STATIC(appl_agentx_sessions, appl_agentx_session, sess_entry,__attribute__((__unused__)) static void appl_agentx_sessions_RB_INSERT_COLOR (struct appl_agentx_sessions *, struct appl_agentx_session *) ; __attribute__((__unused__)) static void appl_agentx_sessions_RB_REMOVE_COLOR (struct appl_agentx_sessions *, struct appl_agentx_session *, struct appl_agentx_session *);__attribute__((__unused__)) static struct appl_agentx_session *appl_agentx_sessions_RB_REMOVE(struct appl_agentx_sessions *, struct appl_agentx_session *); __attribute__ ((__unused__)) static struct appl_agentx_session *appl_agentx_sessions_RB_INSERT (struct appl_agentx_sessions *, struct appl_agentx_session *) ; __attribute__((__unused__)) static struct appl_agentx_session *appl_agentx_sessions_RB_FIND(struct appl_agentx_sessions *, struct appl_agentx_session *); __attribute__((__unused__)) static struct appl_agentx_session *appl_agentx_sessions_RB_NFIND(struct appl_agentx_sessions *, struct appl_agentx_session *); __attribute__ ((__unused__)) static struct appl_agentx_session *appl_agentx_sessions_RB_NEXT (struct appl_agentx_session *); __attribute__((__unused__)) static struct appl_agentx_session *appl_agentx_sessions_RB_PREV(struct appl_agentx_session *); __attribute__((__unused__)) static struct appl_agentx_session *appl_agentx_sessions_RB_MINMAX(struct appl_agentx_sessions *, int); | |||
121 | appl_agentx_session_cmp)__attribute__((__unused__)) static void appl_agentx_sessions_RB_INSERT_COLOR (struct appl_agentx_sessions *, struct appl_agentx_session *) ; __attribute__((__unused__)) static void appl_agentx_sessions_RB_REMOVE_COLOR (struct appl_agentx_sessions *, struct appl_agentx_session *, struct appl_agentx_session *);__attribute__((__unused__)) static struct appl_agentx_session *appl_agentx_sessions_RB_REMOVE(struct appl_agentx_sessions *, struct appl_agentx_session *); __attribute__ ((__unused__)) static struct appl_agentx_session *appl_agentx_sessions_RB_INSERT (struct appl_agentx_sessions *, struct appl_agentx_session *) ; __attribute__((__unused__)) static struct appl_agentx_session *appl_agentx_sessions_RB_FIND(struct appl_agentx_sessions *, struct appl_agentx_session *); __attribute__((__unused__)) static struct appl_agentx_session *appl_agentx_sessions_RB_NFIND(struct appl_agentx_sessions *, struct appl_agentx_session *); __attribute__ ((__unused__)) static struct appl_agentx_session *appl_agentx_sessions_RB_NEXT (struct appl_agentx_session *); __attribute__((__unused__)) static struct appl_agentx_session *appl_agentx_sessions_RB_PREV(struct appl_agentx_session *); __attribute__((__unused__)) static struct appl_agentx_session *appl_agentx_sessions_RB_MINMAX(struct appl_agentx_sessions *, int);; | |||
122 | ||||
123 | void | |||
124 | appl_agentx(void) | |||
125 | { | |||
126 | struct agentx_master *master; | |||
127 | ||||
128 | TAILQ_FOREACH(master, &(snmpd_env->sc_agentx_masters), axm_entry)for((master) = ((&(snmpd_env->sc_agentx_masters))-> tqh_first); (master) != ((void *)0); (master) = ((master)-> axm_entry.tqe_next)) | |||
129 | appl_agentx_listen(master); | |||
130 | } | |||
131 | ||||
132 | void | |||
133 | appl_agentx_init(void) | |||
134 | { | |||
135 | struct agentx_master *master; | |||
136 | ||||
137 | TAILQ_FOREACH(master, &(snmpd_env->sc_agentx_masters), axm_entry)for((master) = ((&(snmpd_env->sc_agentx_masters))-> tqh_first); (master) != ((void *)0); (master) = ((master)-> axm_entry.tqe_next)) { | |||
138 | if (master->axm_fd == -1) | |||
139 | continue; | |||
140 | event_set(&(master->axm_ev), master->axm_fd, | |||
141 | EV_READ0x02 | EV_PERSIST0x10, appl_agentx_accept, master); | |||
142 | event_add(&(master->axm_ev), NULL((void *)0)); | |||
143 | log_info("AgentX: listening on %s", master->axm_sun.sun_path); | |||
144 | } | |||
145 | } | |||
146 | void | |||
147 | appl_agentx_listen(struct agentx_master *master) | |||
148 | { | |||
149 | mode_t mask; | |||
150 | ||||
151 | unlink(master->axm_sun.sun_path); | |||
152 | ||||
153 | mask = umask(0777); | |||
154 | if ((master->axm_fd = socket(AF_UNIX1, SOCK_STREAM1, 0)) == -1 || | |||
155 | bind(master->axm_fd, (struct sockaddr *)&(master->axm_sun), | |||
156 | sizeof(master->axm_sun)) == -1 || | |||
157 | listen(master->axm_fd, 5)) { | |||
158 | log_warn("AgentX: listen %s", master->axm_sun.sun_path); | |||
159 | umask(mask); | |||
160 | return; | |||
161 | } | |||
162 | umask(mask); | |||
163 | if (chown(master->axm_sun.sun_path, master->axm_owner, | |||
164 | master->axm_group) == -1) { | |||
165 | log_warn("AgentX: chown %s", master->axm_sun.sun_path); | |||
166 | goto fail; | |||
167 | } | |||
168 | if (chmod(master->axm_sun.sun_path, master->axm_mode) == -1) { | |||
169 | log_warn("AgentX: chmod %s", master->axm_sun.sun_path); | |||
170 | goto fail; | |||
171 | } | |||
172 | return; | |||
173 | fail: | |||
174 | close(master->axm_fd); | |||
175 | master->axm_fd = -1; | |||
176 | } | |||
177 | ||||
178 | void | |||
179 | appl_agentx_shutdown(void) | |||
180 | { | |||
181 | struct appl_agentx_connection *conn, *tconn; | |||
182 | ||||
183 | RB_FOREACH_SAFE(conn, appl_agentx_conns, &appl_agentx_conns, tconn)for ((conn) = appl_agentx_conns_RB_MINMAX(&appl_agentx_conns , -1); ((conn) != ((void *)0)) && ((tconn) = appl_agentx_conns_RB_NEXT (conn), 1); (conn) = (tconn)) | |||
| ||||
184 | appl_agentx_free(conn, APPL_CLOSE_REASONSHUTDOWN); | |||
185 | } | |||
186 | ||||
187 | void | |||
188 | appl_agentx_accept(int masterfd, short event, void *cookie) | |||
189 | { | |||
190 | int fd; | |||
191 | struct agentx_master *master = cookie; | |||
192 | struct sockaddr_un sun; | |||
193 | socklen_t sunlen = sizeof(sun); | |||
194 | struct appl_agentx_connection *conn = NULL((void *)0); | |||
195 | ||||
196 | if ((fd = accept(masterfd, (struct sockaddr *)&sun, &sunlen)) == -1) { | |||
197 | log_warn("AgentX: accept %s", master->axm_sun.sun_path); | |||
198 | return; | |||
199 | } | |||
200 | ||||
201 | if ((conn = malloc(sizeof(*conn))) == NULL((void *)0)) { | |||
202 | log_warn(NULL((void *)0)); | |||
203 | goto fail; | |||
204 | } | |||
205 | ||||
206 | conn->conn_backend = 0; | |||
207 | TAILQ_INIT(&(conn->conn_sessions))do { (&(conn->conn_sessions))->tqh_first = ((void * )0); (&(conn->conn_sessions))->tqh_last = &(& (conn->conn_sessions))->tqh_first; } while (0); | |||
208 | if ((conn->conn_ax = ax_new(fd)) == NULL((void *)0)) { | |||
209 | log_warn(NULL((void *)0)); | |||
210 | goto fail; | |||
211 | } | |||
212 | ||||
213 | do { | |||
214 | conn->conn_id = arc4random(); | |||
215 | } while (RB_INSERT(appl_agentx_conns,appl_agentx_conns_RB_INSERT(&appl_agentx_conns, conn) | |||
216 | &appl_agentx_conns, conn)appl_agentx_conns_RB_INSERT(&appl_agentx_conns, conn) != NULL((void *)0)); | |||
217 | ||||
218 | event_set(&(conn->conn_rev), fd, EV_READ0x02 | EV_PERSIST0x10, | |||
219 | appl_agentx_recv, conn); | |||
220 | event_add(&(conn->conn_rev), NULL((void *)0)); | |||
221 | event_set(&(conn->conn_wev), fd, EV_WRITE0x04, appl_agentx_send, conn); | |||
222 | log_info("AgentX(%"PRIu32"u""): new connection", conn->conn_id); | |||
223 | ||||
224 | return; | |||
225 | fail: | |||
226 | close(fd); | |||
227 | free(conn); | |||
228 | } | |||
229 | ||||
230 | void | |||
231 | appl_agentx_backend(int fd) | |||
232 | { | |||
233 | struct appl_agentx_connection *conn; | |||
234 | ||||
235 | if ((conn = malloc(sizeof(*conn))) == NULL((void *)0)) | |||
236 | fatal(NULL((void *)0)); | |||
237 | ||||
238 | conn->conn_backend = 1; | |||
239 | TAILQ_INIT(&(conn->conn_sessions))do { (&(conn->conn_sessions))->tqh_first = ((void * )0); (&(conn->conn_sessions))->tqh_last = &(& (conn->conn_sessions))->tqh_first; } while (0); | |||
240 | if ((conn->conn_ax = ax_new(fd)) == NULL((void *)0)) | |||
241 | fatal("ax_new"); | |||
242 | ||||
243 | do { | |||
244 | conn->conn_id = arc4random(); | |||
245 | } while (RB_INSERT(appl_agentx_conns,appl_agentx_conns_RB_INSERT(&appl_agentx_conns, conn) | |||
246 | &appl_agentx_conns, conn)appl_agentx_conns_RB_INSERT(&appl_agentx_conns, conn) != NULL((void *)0)); | |||
247 | ||||
248 | event_set(&(conn->conn_rev), fd, EV_READ0x02 | EV_PERSIST0x10, | |||
249 | appl_agentx_recv, conn); | |||
250 | event_add(&(conn->conn_rev), NULL((void *)0)); | |||
251 | event_set(&(conn->conn_wev), fd, EV_WRITE0x04, appl_agentx_send, conn); | |||
252 | } | |||
253 | ||||
254 | void | |||
255 | appl_agentx_free(struct appl_agentx_connection *conn, | |||
256 | enum appl_close_reason reason) | |||
257 | { | |||
258 | struct appl_agentx_session *session; | |||
259 | ||||
260 | while ((session = TAILQ_FIRST(&(conn->conn_sessions))((&(conn->conn_sessions))->tqh_first)) != NULL((void *)0)) { | |||
261 | if (conn->conn_ax
| |||
262 | appl_agentx_session_free(session); | |||
| ||||
263 | else | |||
264 | appl_agentx_forceclose(&(session->sess_backend), | |||
265 | reason); | |||
266 | } | |||
267 | ||||
268 | event_del(&(conn->conn_rev)); | |||
269 | event_del(&(conn->conn_wev)); | |||
270 | ||||
271 | RB_REMOVE(appl_agentx_conns, &appl_agentx_conns, conn)appl_agentx_conns_RB_REMOVE(&appl_agentx_conns, conn); | |||
272 | if (conn->conn_ax != NULL((void *)0)) | |||
273 | (void)ax_send(conn->conn_ax); | |||
274 | ax_free(conn->conn_ax); | |||
275 | if (conn->conn_backend) | |||
276 | fatalx("AgentX(%"PRIu32"u""): disappeared unexpected", | |||
277 | conn->conn_id); | |||
278 | free(conn); | |||
279 | } | |||
280 | ||||
281 | void | |||
282 | appl_agentx_recv(int fd, short event, void *cookie) | |||
283 | { | |||
284 | struct appl_agentx_connection *conn = cookie; | |||
285 | struct appl_agentx_session *session = NULL((void *)0); | |||
286 | struct ax_pdu *pdu; | |||
287 | enum appl_error error; | |||
288 | char name[100]; | |||
289 | ||||
290 | snprintf(name, sizeof(name), "AgentX(%"PRIu32"u"")", conn->conn_id); | |||
291 | if ((pdu = ax_recv(conn->conn_ax)) == NULL((void *)0)) { | |||
292 | if (errno(*__errno()) == EAGAIN35) | |||
293 | return; | |||
294 | log_warn("%s", name); | |||
295 | /* | |||
296 | * Either the connection is dead, or we had garbage on the line. | |||
297 | * Both make sure we can't continue on this stream. | |||
298 | */ | |||
299 | if (errno(*__errno()) == ECONNRESET54) { | |||
300 | ax_free(conn->conn_ax); | |||
301 | conn->conn_ax = NULL((void *)0); | |||
302 | } | |||
303 | appl_agentx_free(conn, errno(*__errno()) == EPROTO95 ? | |||
304 | APPL_CLOSE_REASONPROTOCOLERROR : APPL_CLOSE_REASONOTHER); | |||
305 | return; | |||
306 | } | |||
307 | ||||
308 | conn->conn_ax->ax_byteorder = pdu->ap_header.aph_flags & | |||
309 | AX_PDU_FLAG_NETWORK_BYTE_ORDER(1 << 4) ? | |||
310 | AX_BYTE_ORDER_BE : AX_BYTE_ORDER_LE; | |||
311 | if (pdu->ap_header.aph_type != AX_PDU_TYPE_OPEN) { | |||
312 | /* Make sure we only look for connection-local sessions */ | |||
313 | TAILQ_FOREACH(session, &(conn->conn_sessions),for((session) = ((&(conn->conn_sessions))->tqh_first ); (session) != ((void *)0); (session) = ((session)->sess_conn_entry .tqe_next)) | |||
314 | sess_conn_entry)for((session) = ((&(conn->conn_sessions))->tqh_first ); (session) != ((void *)0); (session) = ((session)->sess_conn_entry .tqe_next)) { | |||
315 | if (session->sess_id == pdu->ap_header.aph_sessionid) | |||
316 | break; | |||
317 | } | |||
318 | if (session == NULL((void *)0)) { | |||
319 | log_warnx("%s: Session %"PRIu32"u"" not found for request", | |||
320 | name, pdu->ap_header.aph_sessionid); | |||
321 | error = APPL_ERROR_NOTOPEN; | |||
322 | goto fail; | |||
323 | } | |||
324 | strlcpy(name, session->sess_backend.ab_name, sizeof(name)); | |||
325 | /* | |||
326 | * RFC2741 section 7.1.1 bullet 4 is unclear on what byte order | |||
327 | * the response should be. My best guess is that it makes more | |||
328 | * sense that replies are in the same byte-order as what was | |||
329 | * requested. | |||
330 | * In practice we always have the same byte order as when we | |||
331 | * opened the session, so it's likely a non-issue, however, we | |||
332 | * can change to session byte order here. | |||
333 | */ | |||
334 | } | |||
335 | ||||
336 | if (pdu->ap_header.aph_flags & AX_PDU_FLAG_INSTANCE_REGISTRATION(1 << 0)) { | |||
337 | if (pdu->ap_header.aph_type != AX_PDU_TYPE_REGISTER) { | |||
338 | log_warnx("%s: %s: Invalid INSTANCE_REGISTRATION flag", | |||
339 | name, ax_pdutype2string(pdu->ap_header.aph_flags)); | |||
340 | error = APPL_ERROR_PARSEERROR; | |||
341 | goto fail; | |||
342 | } | |||
343 | } | |||
344 | if (pdu->ap_header.aph_flags & AX_PDU_FLAG_NEW_INDEX(1 << 1)) { | |||
345 | if (pdu->ap_header.aph_type != AX_PDU_TYPE_INDEXALLOCATE && | |||
346 | pdu->ap_header.aph_type != AX_PDU_TYPE_INDEXDEALLOCATE) { | |||
347 | log_warnx("%s: %s: Invalid NEW_INDEX flag", name, | |||
348 | ax_pdutype2string(pdu->ap_header.aph_flags)); | |||
349 | error = APPL_ERROR_PARSEERROR; | |||
350 | goto fail; | |||
351 | } | |||
352 | } | |||
353 | if (pdu->ap_header.aph_flags & AX_PDU_FLAG_ANY_INDEX(1 << 2)) { | |||
354 | if (pdu->ap_header.aph_type != AX_PDU_TYPE_INDEXALLOCATE && | |||
355 | pdu->ap_header.aph_type != AX_PDU_TYPE_INDEXDEALLOCATE) { | |||
356 | log_warnx("%s: %s: Invalid ANY_INDEX flag", name, | |||
357 | ax_pdutype2string(pdu->ap_header.aph_flags)); | |||
358 | error = APPL_ERROR_PARSEERROR; | |||
359 | goto fail; | |||
360 | } | |||
361 | } | |||
362 | if (pdu->ap_header.aph_flags & AX_PDU_FLAG_NON_DEFAULT_CONTEXT(1 << 3)) { | |||
363 | if (pdu->ap_header.aph_type != AX_PDU_TYPE_REGISTER && | |||
364 | pdu->ap_header.aph_type != AX_PDU_TYPE_UNREGISTER && | |||
365 | pdu->ap_header.aph_type != AX_PDU_TYPE_ADDAGENTCAPS && | |||
366 | pdu->ap_header.aph_type != AX_PDU_TYPE_REMOVEAGENTCAPS && | |||
367 | pdu->ap_header.aph_type != AX_PDU_TYPE_GET && | |||
368 | pdu->ap_header.aph_type != AX_PDU_TYPE_GETNEXT && | |||
369 | pdu->ap_header.aph_type != AX_PDU_TYPE_GETBULK && | |||
370 | pdu->ap_header.aph_type != AX_PDU_TYPE_INDEXALLOCATE && | |||
371 | pdu->ap_header.aph_type != AX_PDU_TYPE_INDEXDEALLOCATE && | |||
372 | pdu->ap_header.aph_type != AX_PDU_TYPE_NOTIFY && | |||
373 | pdu->ap_header.aph_type != AX_PDU_TYPE_TESTSET && | |||
374 | pdu->ap_header.aph_type != AX_PDU_TYPE_PING) { | |||
375 | log_warnx("%s: %s: Invalid NON_DEFAULT_CONTEXT flag", | |||
376 | name, ax_pdutype2string(pdu->ap_header.aph_flags)); | |||
377 | error = APPL_ERROR_PARSEERROR; | |||
378 | goto fail; | |||
379 | } | |||
380 | if (appl_context(pdu->ap_context.aos_string, 0) == NULL((void *)0)) { | |||
381 | log_warnx("%s: %s: Unsupported context", | |||
382 | name, ax_pdutype2string(pdu->ap_header.aph_flags)); | |||
383 | error = APPL_ERROR_UNSUPPORTEDCONTEXT; | |||
384 | goto fail; | |||
385 | } | |||
386 | } | |||
387 | switch (pdu->ap_header.aph_type) { | |||
388 | case AX_PDU_TYPE_OPEN: | |||
389 | appl_agentx_open(conn, pdu); | |||
390 | break; | |||
391 | case AX_PDU_TYPE_CLOSE: | |||
392 | appl_agentx_close(session, pdu); | |||
393 | break; | |||
394 | case AX_PDU_TYPE_REGISTER: | |||
395 | appl_agentx_register(session, pdu); | |||
396 | break; | |||
397 | case AX_PDU_TYPE_UNREGISTER: | |||
398 | appl_agentx_unregister(session, pdu); | |||
399 | break; | |||
400 | case AX_PDU_TYPE_GET: | |||
401 | case AX_PDU_TYPE_GETNEXT: | |||
402 | case AX_PDU_TYPE_GETBULK: | |||
403 | case AX_PDU_TYPE_TESTSET: | |||
404 | case AX_PDU_TYPE_COMMITSET: | |||
405 | case AX_PDU_TYPE_UNDOSET: | |||
406 | case AX_PDU_TYPE_CLEANUPSET: | |||
407 | log_warnx("%s: %s: Not an adminsitrative message", name, | |||
408 | ax_pdutype2string(pdu->ap_header.aph_type)); | |||
409 | error = APPL_ERROR_PARSEERROR; | |||
410 | goto fail; | |||
411 | case AX_PDU_TYPE_NOTIFY: | |||
412 | log_warnx("%s: %s: not supported", name, | |||
413 | ax_pdutype2string(pdu->ap_header.aph_type)); | |||
414 | /* | |||
415 | * RFC 2741 section 7.1.10: | |||
416 | * Note that the master agent's successful response indicates | |||
417 | * the agentx-Notify-PDU was received and validated. It does | |||
418 | * not indicate that any particular notifications were actually | |||
419 | * generated or received by notification targets | |||
420 | */ | |||
421 | /* XXX Not yet - FALLTHROUGH */ | |||
422 | case AX_PDU_TYPE_PING: | |||
423 | ax_response(conn->conn_ax, pdu->ap_header.aph_sessionid, | |||
424 | pdu->ap_header.aph_transactionid, | |||
425 | pdu->ap_header.aph_packetid, smi_getticks(), | |||
426 | APPL_ERROR_NOERROR, 0, NULL((void *)0), 0); | |||
427 | event_add(&(conn->conn_wev), NULL((void *)0)); | |||
428 | break; | |||
429 | case AX_PDU_TYPE_INDEXALLOCATE: | |||
430 | case AX_PDU_TYPE_INDEXDEALLOCATE: | |||
431 | log_warnx("%s: %s: not supported", name, | |||
432 | ax_pdutype2string(pdu->ap_header.aph_type)); | |||
433 | ax_response(conn->conn_ax, pdu->ap_header.aph_sessionid, | |||
434 | pdu->ap_header.aph_transactionid, | |||
435 | pdu->ap_header.aph_packetid, smi_getticks(), | |||
436 | APPL_ERROR_PROCESSINGERROR, 1, | |||
437 | pdu->ap_payload.ap_vbl.ap_varbind, | |||
438 | pdu->ap_payload.ap_vbl.ap_nvarbind); | |||
439 | event_add(&(conn->conn_wev), NULL((void *)0)); | |||
440 | break; | |||
441 | case AX_PDU_TYPE_ADDAGENTCAPS: | |||
442 | appl_agentx_addagentcaps(session, pdu); | |||
443 | break; | |||
444 | case AX_PDU_TYPE_REMOVEAGENTCAPS: | |||
445 | appl_agentx_removeagentcaps(session, pdu); | |||
446 | break; | |||
447 | case AX_PDU_TYPE_RESPONSE: | |||
448 | appl_agentx_response(session, pdu); | |||
449 | break; | |||
450 | } | |||
451 | ||||
452 | ax_pdu_free(pdu); | |||
453 | return; | |||
454 | fail: | |||
455 | ax_response(conn->conn_ax, pdu->ap_header.aph_sessionid, | |||
456 | pdu->ap_header.aph_transactionid, | |||
457 | pdu->ap_header.aph_packetid, smi_getticks(), | |||
458 | error, 0, NULL((void *)0), 0); | |||
459 | event_add(&(conn->conn_wev), NULL((void *)0)); | |||
460 | ax_pdu_free(pdu); | |||
461 | ||||
462 | if (session == NULL((void *)0) || error != APPL_ERROR_PARSEERROR) | |||
463 | return; | |||
464 | ||||
465 | appl_agentx_forceclose(&(session->sess_backend), | |||
466 | APPL_CLOSE_REASONPARSEERROR); | |||
467 | if (TAILQ_EMPTY(&(conn->conn_sessions))(((&(conn->conn_sessions))->tqh_first) == ((void *) 0))) | |||
468 | appl_agentx_free(conn, APPL_CLOSE_REASONOTHER); | |||
469 | } | |||
470 | ||||
471 | void | |||
472 | appl_agentx_open(struct appl_agentx_connection *conn, struct ax_pdu *pdu) | |||
473 | { | |||
474 | struct appl_agentx_session *session; | |||
475 | struct ber_oid oid; | |||
476 | char oidbuf[1024]; | |||
477 | enum appl_error error = APPL_ERROR_NOERROR; | |||
478 | ||||
479 | if ((session = malloc(sizeof(*session))) == NULL((void *)0)) { | |||
480 | log_warn(NULL((void *)0)); | |||
481 | error = APPL_ERROR_OPENFAILED; | |||
482 | goto fail; | |||
483 | } | |||
484 | session->sess_descr.aos_string = NULL((void *)0); | |||
485 | ||||
486 | session->sess_conn = conn; | |||
487 | if (pdu->ap_header.aph_flags & AX_PDU_FLAG_NETWORK_BYTE_ORDER(1 << 4)) | |||
488 | session->sess_byteorder = AX_BYTE_ORDER_BE; | |||
489 | else | |||
490 | session->sess_byteorder = AX_BYTE_ORDER_LE; | |||
491 | ||||
492 | /* RFC 2742 agentxSessionObjectID */ | |||
493 | if (pdu->ap_payload.ap_open.ap_oid.aoi_idlen == 0) { | |||
494 | pdu->ap_payload.ap_open.ap_oid.aoi_id[0] = 0; | |||
495 | pdu->ap_payload.ap_open.ap_oid.aoi_id[1] = 0; | |||
496 | pdu->ap_payload.ap_open.ap_oid.aoi_idlen = 2; | |||
497 | } else if (pdu->ap_payload.ap_open.ap_oid.aoi_idlen == 1) { | |||
498 | log_warnx("AgentX(%"PRIu32"u""): Invalid oid: Open Failed", | |||
499 | conn->conn_id); | |||
500 | error = APPL_ERROR_PARSEERROR; | |||
501 | goto fail; | |||
502 | } | |||
503 | /* RFC 2742 agentxSessionDescr */ | |||
504 | if (pdu->ap_payload.ap_open.ap_descr.aos_slen > 255) { | |||
505 | log_warnx("AgentX(%"PRIu32"u""): Invalid descr (too long): Open " | |||
506 | "Failed", conn->conn_id); | |||
507 | error = APPL_ERROR_PARSEERROR; | |||
508 | goto fail; | |||
509 | } | |||
510 | /* | |||
511 | * ax_ostring is always NUL-terminated, but doesn't scan for internal | |||
512 | * NUL-bytes. However, mbstowcs stops at NUL, which might be in the | |||
513 | * middle of the string. | |||
514 | */ | |||
515 | if (strlen(pdu->ap_payload.ap_open.ap_descr.aos_string) != | |||
516 | pdu->ap_payload.ap_open.ap_descr.aos_slen || | |||
517 | mbstowcs(NULL((void *)0), | |||
518 | pdu->ap_payload.ap_open.ap_descr.aos_string, 0) == (size_t)-1) { | |||
519 | log_warnx("AgentX(%"PRIu32"u""): Invalid descr (not UTF-8): " | |||
520 | "Open Failed", conn->conn_id); | |||
521 | error = APPL_ERROR_PARSEERROR; | |||
522 | goto fail; | |||
523 | } | |||
524 | ||||
525 | session->sess_timeout = pdu->ap_payload.ap_open.ap_timeout; | |||
526 | session->sess_oid = pdu->ap_payload.ap_open.ap_oid; | |||
527 | session->sess_descr.aos_slen = pdu->ap_payload.ap_open.ap_descr.aos_slen; | |||
528 | if (pdu->ap_payload.ap_open.ap_descr.aos_string != NULL((void *)0)) { | |||
529 | session->sess_descr.aos_string = | |||
530 | strdup(pdu->ap_payload.ap_open.ap_descr.aos_string); | |||
531 | if (session->sess_descr.aos_string == NULL((void *)0)) { | |||
532 | log_warn("AgentX(%"PRIu32"u""): strdup: Open Failed", | |||
533 | conn->conn_id); | |||
534 | error = APPL_ERROR_OPENFAILED; | |||
535 | goto fail; | |||
536 | } | |||
537 | } | |||
538 | ||||
539 | /* RFC 2742 agentxSessionIndex: chances of reuse, slim to none */ | |||
540 | do { | |||
541 | session->sess_id = arc4random(); | |||
542 | } while (RB_INSERT(appl_agentx_sessions,appl_agentx_sessions_RB_INSERT(&appl_agentx_sessions, session ) | |||
543 | &appl_agentx_sessions, session)appl_agentx_sessions_RB_INSERT(&appl_agentx_sessions, session ) != NULL((void *)0)); | |||
544 | ||||
545 | if (asprintf(&(session->sess_backend.ab_name), | |||
546 | "AgentX(%"PRIu32"u""/%"PRIu32"u"")", | |||
547 | conn->conn_id, session->sess_id) == -1) { | |||
548 | log_warn("AgentX(%"PRIu32"u""): asprintf: Open Failed", | |||
549 | conn->conn_id); | |||
550 | error = APPL_ERROR_OPENFAILED; | |||
551 | goto fail; | |||
552 | } | |||
553 | session->sess_backend.ab_cookie = session; | |||
554 | session->sess_backend.ab_retries = 0; | |||
555 | session->sess_backend.ab_fn = &appl_agentx_functions; | |||
556 | session->sess_backend.ab_range = 1; | |||
557 | RB_INIT(&(session->sess_backend.ab_requests))do { (&(session->sess_backend.ab_requests))->rbh_root = ((void *)0); } while (0); | |||
558 | TAILQ_INSERT_TAIL(&(conn->conn_sessions), session, sess_conn_entry)do { (session)->sess_conn_entry.tqe_next = ((void *)0); (session )->sess_conn_entry.tqe_prev = (&(conn->conn_sessions ))->tqh_last; *(&(conn->conn_sessions))->tqh_last = (session); (&(conn->conn_sessions))->tqh_last = & (session)->sess_conn_entry.tqe_next; } while (0); | |||
559 | ||||
560 | appl_agentx_oid2ber_oid(&(session->sess_oid), &oid); | |||
561 | smi_oid2string(&oid, oidbuf, sizeof(oidbuf), 0); | |||
562 | log_info("%s: %s %s: Open", session->sess_backend.ab_name, oidbuf, | |||
563 | session->sess_descr.aos_string); | |||
564 | ||||
565 | ax_response(conn->conn_ax, session->sess_id, | |||
566 | pdu->ap_header.aph_transactionid, pdu->ap_header.aph_packetid, | |||
567 | smi_getticks(), APPL_ERROR_NOERROR, 0, NULL((void *)0), 0); | |||
568 | event_add(&(conn->conn_wev), NULL((void *)0)); | |||
569 | ||||
570 | return; | |||
571 | fail: | |||
572 | ax_response(conn->conn_ax, 0, pdu->ap_header.aph_transactionid, | |||
573 | pdu->ap_header.aph_packetid, 0, error, 0, NULL((void *)0), 0); | |||
574 | event_add(&(conn->conn_wev), NULL((void *)0)); | |||
575 | if (session != NULL((void *)0)) | |||
576 | free(session->sess_descr.aos_string); | |||
577 | free(session); | |||
578 | } | |||
579 | ||||
580 | void | |||
581 | appl_agentx_close(struct appl_agentx_session *session, struct ax_pdu *pdu) | |||
582 | { | |||
583 | struct appl_agentx_connection *conn = session->sess_conn; | |||
584 | char name[100]; | |||
585 | enum appl_error error = APPL_ERROR_NOERROR; | |||
586 | ||||
587 | strlcpy(name, session->sess_backend.ab_name, sizeof(name)); | |||
588 | if (pdu->ap_payload.ap_close.ap_reason == AX_CLOSE_BYMANAGER) { | |||
589 | log_warnx("%s: Invalid close reason", name); | |||
590 | error = APPL_ERROR_PARSEERROR; | |||
591 | } else { | |||
592 | appl_agentx_session_free(session); | |||
593 | log_info("%s: Closed by subagent (%s)", name, | |||
594 | ax_closereason2string(pdu->ap_payload.ap_close.ap_reason)); | |||
595 | } | |||
596 | ||||
597 | ax_response(conn->conn_ax, pdu->ap_header.aph_sessionid, | |||
598 | pdu->ap_header.aph_transactionid, pdu->ap_header.aph_packetid, | |||
599 | smi_getticks(), error, 0, NULL((void *)0), 0); | |||
600 | event_add(&(conn->conn_wev), NULL((void *)0)); | |||
601 | if (error == APPL_ERROR_NOERROR) | |||
602 | return; | |||
603 | ||||
604 | appl_agentx_forceclose(&(session->sess_backend), | |||
605 | APPL_CLOSE_REASONPARSEERROR); | |||
606 | if (TAILQ_EMPTY(&(conn->conn_sessions))(((&(conn->conn_sessions))->tqh_first) == ((void *) 0))) | |||
607 | appl_agentx_free(conn, APPL_CLOSE_REASONOTHER); | |||
608 | } | |||
609 | ||||
610 | void | |||
611 | appl_agentx_forceclose(struct appl_backend *backend, | |||
612 | enum appl_close_reason reason) | |||
613 | { | |||
614 | struct appl_agentx_session *session = backend->ab_cookie; | |||
615 | char name[100]; | |||
616 | ||||
617 | session->sess_conn->conn_ax->ax_byteorder = session->sess_byteorder; | |||
618 | ax_close(session->sess_conn->conn_ax, session->sess_id, | |||
619 | (enum ax_close_reason) reason); | |||
620 | event_add(&(session->sess_conn->conn_wev), NULL((void *)0)); | |||
621 | ||||
622 | strlcpy(name, session->sess_backend.ab_name, sizeof(name)); | |||
623 | appl_agentx_session_free(session); | |||
624 | log_info("%s: Closed by snmpd (%s)", name, | |||
625 | ax_closereason2string((enum ax_close_reason)reason)); | |||
626 | } | |||
627 | ||||
628 | void | |||
629 | appl_agentx_session_free(struct appl_agentx_session *session) | |||
630 | { | |||
631 | struct appl_agentx_connection *conn = session->sess_conn; | |||
632 | ||||
633 | appl_close(&(session->sess_backend)); | |||
634 | ||||
635 | RB_REMOVE(appl_agentx_sessions, &appl_agentx_sessions, session)appl_agentx_sessions_RB_REMOVE(&appl_agentx_sessions, session ); | |||
636 | TAILQ_REMOVE(&(conn->conn_sessions), session, sess_conn_entry)do { if (((session)->sess_conn_entry.tqe_next) != ((void * )0)) (session)->sess_conn_entry.tqe_next->sess_conn_entry .tqe_prev = (session)->sess_conn_entry.tqe_prev; else (& (conn->conn_sessions))->tqh_last = (session)->sess_conn_entry .tqe_prev; *(session)->sess_conn_entry.tqe_prev = (session )->sess_conn_entry.tqe_next; ; ; } while (0); | |||
637 | ||||
638 | free(session->sess_backend.ab_name); | |||
639 | free(session->sess_descr.aos_string); | |||
640 | free(session); | |||
641 | } | |||
642 | ||||
643 | void | |||
644 | appl_agentx_register(struct appl_agentx_session *session, struct ax_pdu *pdu) | |||
645 | { | |||
646 | uint32_t timeout; | |||
647 | struct ber_oid oid; | |||
648 | enum appl_error error; | |||
649 | int subtree = 0; | |||
650 | ||||
651 | timeout = pdu->ap_payload.ap_register.ap_timeout; | |||
652 | timeout = timeout != 0 ? timeout : session->sess_timeout != 0 ? | |||
653 | session->sess_timeout : AGENTX_DEFAULTTIMEOUT5; | |||
654 | timeout *= 100; | |||
655 | ||||
656 | if (session->sess_conn->conn_backend) { | |||
657 | pdu->ap_payload.ap_register.ap_priority = 1; | |||
658 | subtree = 1; | |||
659 | } | |||
660 | if (appl_agentx_oid2ber_oid( | |||
661 | &(pdu->ap_payload.ap_register.ap_subtree), &oid) == NULL((void *)0)) { | |||
662 | log_warnx("%s: Failed to register: oid too small", | |||
663 | session->sess_backend.ab_name); | |||
664 | error = APPL_ERROR_PROCESSINGERROR; | |||
665 | goto fail; | |||
666 | } | |||
667 | ||||
668 | error = appl_register(pdu->ap_context.aos_string, timeout, | |||
669 | pdu->ap_payload.ap_register.ap_priority, &oid, | |||
670 | pdu->ap_header.aph_flags & AX_PDU_FLAG_INSTANCE_REGISTRATION(1 << 0), | |||
671 | subtree, pdu->ap_payload.ap_register.ap_range_subid, | |||
672 | pdu->ap_payload.ap_register.ap_upper_bound, | |||
673 | &(session->sess_backend)); | |||
674 | ||||
675 | fail: | |||
676 | ax_response(session->sess_conn->conn_ax, session->sess_id, | |||
677 | pdu->ap_header.aph_transactionid, pdu->ap_header.aph_packetid, | |||
678 | smi_getticks(), error, 0, NULL((void *)0), 0); | |||
679 | event_add(&(session->sess_conn->conn_wev), NULL((void *)0)); | |||
680 | } | |||
681 | ||||
682 | void | |||
683 | appl_agentx_unregister(struct appl_agentx_session *session, struct ax_pdu *pdu) | |||
684 | { | |||
685 | struct ber_oid oid; | |||
686 | enum appl_error error; | |||
687 | ||||
688 | if (appl_agentx_oid2ber_oid( | |||
689 | &(pdu->ap_payload.ap_unregister.ap_subtree), &oid) == NULL((void *)0)) { | |||
690 | log_warnx("%s: Failed to unregister: oid too small", | |||
691 | session->sess_backend.ab_name); | |||
692 | error = APPL_ERROR_PROCESSINGERROR; | |||
693 | goto fail; | |||
694 | } | |||
695 | ||||
696 | error = appl_unregister(pdu->ap_context.aos_string, | |||
697 | pdu->ap_payload.ap_unregister.ap_priority, &oid, | |||
698 | pdu->ap_payload.ap_unregister.ap_range_subid, | |||
699 | pdu->ap_payload.ap_unregister.ap_upper_bound, | |||
700 | &(session->sess_backend)); | |||
701 | ||||
702 | fail: | |||
703 | ax_response(session->sess_conn->conn_ax, session->sess_id, | |||
704 | pdu->ap_header.aph_transactionid, pdu->ap_header.aph_packetid, | |||
705 | smi_getticks(), error, 0, NULL((void *)0), 0); | |||
706 | event_add(&(session->sess_conn->conn_wev), NULL((void *)0)); | |||
707 | } | |||
708 | ||||
709 | #define AX_PDU_FLAG_INDEX((1 << 1) | (1 << 2)) (AX_PDU_FLAG_NEW_INDEX(1 << 1) | AX_PDU_FLAG_ANY_INDEX(1 << 2)) | |||
710 | ||||
711 | void | |||
712 | appl_agentx_get(struct appl_backend *backend, int32_t transactionid, | |||
713 | int32_t requestid, const char *ctx, struct appl_varbind *vblist) | |||
714 | { | |||
715 | struct appl_agentx_session *session = backend->ab_cookie; | |||
716 | struct ax_ostring *context, string; | |||
717 | struct appl_varbind *vb; | |||
718 | struct ax_searchrange *srl; | |||
719 | size_t i, j, nsr; | |||
720 | ||||
721 | if (session->sess_conn->conn_ax == NULL((void *)0)) | |||
722 | return; | |||
723 | ||||
724 | for (nsr = 0, vb = vblist; vb != NULL((void *)0); vb = vb->av_next) | |||
725 | nsr++; | |||
726 | ||||
727 | if ((srl = calloc(nsr, sizeof(*srl))) == NULL((void *)0)) { | |||
728 | log_warn(NULL((void *)0)); | |||
729 | appl_response(backend, requestid, APPL_ERROR_GENERR, 1, vblist); | |||
730 | return; | |||
731 | } | |||
732 | ||||
733 | for (i = 0, vb = vblist; i < nsr; i++, vb = vb->av_next) { | |||
734 | srl[i].asr_start.aoi_include = vb->av_include; | |||
735 | srl[i].asr_start.aoi_idlen = vb->av_oid.bo_n; | |||
736 | for (j = 0; j < vb->av_oid.bo_n; j++) | |||
737 | srl[i].asr_start.aoi_id[j] = vb->av_oid.bo_id[j]; | |||
738 | srl[i].asr_stop.aoi_include = 0; | |||
739 | srl[i].asr_stop.aoi_idlen = 0; | |||
740 | } | |||
741 | if ((context = appl_agentx_string2ostring(ctx, &string)) == NULL((void *)0)) { | |||
742 | if (errno(*__errno()) != 0) { | |||
743 | log_warn("Failed to convert context"); | |||
744 | appl_response(backend, requestid, | |||
745 | APPL_ERROR_GENERR, 1, vblist); | |||
746 | free(srl); | |||
747 | return; | |||
748 | } | |||
749 | } | |||
750 | ||||
751 | session->sess_conn->conn_ax->ax_byteorder = session->sess_byteorder; | |||
752 | if (ax_get(session->sess_conn->conn_ax, session->sess_id, transactionid, | |||
753 | requestid, context, srl, nsr) == -1) | |||
754 | appl_response(backend, requestid, APPL_ERROR_GENERR, 1, vblist); | |||
755 | else | |||
756 | event_add(&(session->sess_conn->conn_wev), NULL((void *)0)); | |||
757 | free(srl); | |||
758 | if (context != NULL((void *)0)) | |||
759 | free(context->aos_string); | |||
760 | } | |||
761 | ||||
762 | void | |||
763 | appl_agentx_getnext(struct appl_backend *backend, int32_t transactionid, | |||
764 | int32_t requestid, const char *ctx, struct appl_varbind *vblist) | |||
765 | { | |||
766 | struct appl_agentx_session *session = backend->ab_cookie; | |||
767 | struct ax_ostring *context, string; | |||
768 | struct appl_varbind *vb; | |||
769 | struct ax_searchrange *srl; | |||
770 | size_t i, j, nsr; | |||
771 | ||||
772 | if (session->sess_conn->conn_ax == NULL((void *)0)) | |||
773 | return; | |||
774 | ||||
775 | for (nsr = 0, vb = vblist; vb != NULL((void *)0); vb = vb->av_next) | |||
776 | nsr++; | |||
777 | ||||
778 | if ((srl = calloc(nsr, sizeof(*srl))) == NULL((void *)0)) { | |||
779 | log_warn(NULL((void *)0)); | |||
780 | appl_response(backend, requestid, APPL_ERROR_GENERR, 1, vblist); | |||
781 | return; | |||
782 | } | |||
783 | ||||
784 | for (i = 0, vb = vblist; i < nsr; i++, vb = vb->av_next) { | |||
785 | srl[i].asr_start.aoi_include = vb->av_include; | |||
786 | srl[i].asr_start.aoi_idlen = vb->av_oid.bo_n; | |||
787 | for (j = 0; j < vb->av_oid.bo_n; j++) | |||
788 | srl[i].asr_start.aoi_id[j] = vb->av_oid.bo_id[j]; | |||
789 | srl[i].asr_stop.aoi_include = 0; | |||
790 | srl[i].asr_stop.aoi_idlen = vb->av_oid_end.bo_n; | |||
791 | for (j = 0; j < vb->av_oid_end.bo_n; j++) | |||
792 | srl[i].asr_stop.aoi_id[j] = vb->av_oid_end.bo_id[j]; | |||
793 | } | |||
794 | if ((context = appl_agentx_string2ostring(ctx, &string)) == NULL((void *)0)) { | |||
795 | if (errno(*__errno()) != 0) { | |||
796 | log_warn("Failed to convert context"); | |||
797 | appl_response(backend, requestid, | |||
798 | APPL_ERROR_GENERR, 1, vblist); | |||
799 | free(srl); | |||
800 | return; | |||
801 | } | |||
802 | } | |||
803 | ||||
804 | session->sess_conn->conn_ax->ax_byteorder = session->sess_byteorder; | |||
805 | if (ax_getnext(session->sess_conn->conn_ax, session->sess_id, transactionid, | |||
806 | requestid, context, srl, nsr) == -1) | |||
807 | appl_response(backend, requestid, APPL_ERROR_GENERR, 1, vblist); | |||
808 | else | |||
809 | event_add(&(session->sess_conn->conn_wev), NULL((void *)0)); | |||
810 | free(srl); | |||
811 | if (context != NULL((void *)0)) | |||
812 | free(context->aos_string); | |||
813 | } | |||
814 | ||||
815 | void | |||
816 | appl_agentx_addagentcaps(struct appl_agentx_session *session, | |||
817 | struct ax_pdu *pdu) | |||
818 | { | |||
819 | struct ber_oid oid; | |||
820 | enum appl_error error; | |||
821 | ||||
822 | if (appl_agentx_oid2ber_oid(&(pdu->ap_payload.ap_addagentcaps.ap_oid), | |||
823 | &oid) == NULL((void *)0)) { | |||
824 | log_warnx("%s: Failed to add agent capabilities: oid too small", | |||
825 | session->sess_backend.ab_name); | |||
826 | error = APPL_ERROR_PARSEERROR; | |||
827 | goto fail; | |||
828 | } | |||
829 | ||||
830 | error = appl_addagentcaps(pdu->ap_context.aos_string, &oid, | |||
831 | pdu->ap_payload.ap_addagentcaps.ap_descr.aos_string, | |||
832 | &(session->sess_backend)); | |||
833 | ||||
834 | fail: | |||
835 | ax_response(session->sess_conn->conn_ax, session->sess_id, | |||
836 | pdu->ap_header.aph_transactionid, pdu->ap_header.aph_packetid, | |||
837 | smi_getticks(), error, 0, NULL((void *)0), 0); | |||
838 | event_add(&(session->sess_conn->conn_wev), NULL((void *)0)); | |||
839 | } | |||
840 | ||||
841 | void | |||
842 | appl_agentx_removeagentcaps(struct appl_agentx_session *session, | |||
843 | struct ax_pdu *pdu) | |||
844 | { | |||
845 | struct ber_oid oid; | |||
846 | enum appl_error error; | |||
847 | ||||
848 | if (appl_agentx_oid2ber_oid(&(pdu->ap_payload.ap_addagentcaps.ap_oid), | |||
849 | &oid) == NULL((void *)0)) { | |||
850 | log_warnx("%s: Failed to remove agent capabilities: " | |||
851 | "oid too small", session->sess_backend.ab_name); | |||
852 | error = APPL_ERROR_PARSEERROR; | |||
853 | goto fail; | |||
854 | } | |||
855 | ||||
856 | error = appl_removeagentcaps(pdu->ap_context.aos_string, &oid, | |||
857 | &(session->sess_backend)); | |||
858 | ||||
859 | fail: | |||
860 | ax_response(session->sess_conn->conn_ax, session->sess_id, | |||
861 | pdu->ap_header.aph_transactionid, pdu->ap_header.aph_packetid, | |||
862 | smi_getticks(), error, 0, NULL((void *)0), 0); | |||
863 | event_add(&(session->sess_conn->conn_wev), NULL((void *)0)); | |||
864 | } | |||
865 | ||||
866 | void | |||
867 | appl_agentx_response(struct appl_agentx_session *session, struct ax_pdu *pdu) | |||
868 | { | |||
869 | struct appl_varbind *response = NULL((void *)0); | |||
870 | struct ax_varbind *vb; | |||
871 | enum appl_error error; | |||
872 | uint16_t index; | |||
873 | size_t i, nvarbind; | |||
874 | ||||
875 | nvarbind = pdu->ap_payload.ap_response.ap_nvarbind; | |||
876 | if ((response = calloc(nvarbind, sizeof(*response))) == NULL((void *)0)) { | |||
877 | log_warn(NULL((void *)0)); | |||
878 | appl_response(&(session->sess_backend), | |||
879 | pdu->ap_header.aph_packetid, | |||
880 | APPL_ERROR_GENERR, 1, NULL((void *)0)); | |||
881 | return; | |||
882 | } | |||
883 | ||||
884 | error = (enum appl_error)pdu->ap_payload.ap_response.ap_error; | |||
885 | index = pdu->ap_payload.ap_response.ap_index; | |||
886 | for (i = 0; i < nvarbind; i++) { | |||
887 | response[i].av_next = i + 1 == nvarbind ? | |||
888 | NULL((void *)0) : &(response[i + 1]); | |||
889 | vb = &(pdu->ap_payload.ap_response.ap_varbindlist[i]); | |||
890 | ||||
891 | if (appl_agentx_oid2ber_oid(&(vb->avb_oid), | |||
892 | &(response[i].av_oid)) == NULL((void *)0)) { | |||
893 | log_warnx("%s: invalid oid", | |||
894 | session->sess_backend.ab_name); | |||
895 | if (error != APPL_ERROR_NOERROR) { | |||
896 | error = APPL_ERROR_GENERR; | |||
897 | index = i + 1; | |||
898 | } | |||
899 | continue; | |||
900 | } | |||
901 | response[i].av_value = appl_agentx_value2ber_element(vb); | |||
902 | if (response[i].av_value == NULL((void *)0)) { | |||
903 | log_warn("%s: Failed to parse response value", | |||
904 | session->sess_backend.ab_name); | |||
905 | if (error != APPL_ERROR_NOERROR) { | |||
906 | error = APPL_ERROR_GENERR; | |||
907 | index = i + 1; | |||
908 | } | |||
909 | } | |||
910 | } | |||
911 | appl_response(&(session->sess_backend), pdu->ap_header.aph_packetid, | |||
912 | error, index, response); | |||
913 | free(response); | |||
914 | } | |||
915 | ||||
916 | void | |||
917 | appl_agentx_send(int fd, short event, void *cookie) | |||
918 | { | |||
919 | struct appl_agentx_connection *conn = cookie; | |||
920 | ||||
921 | switch (ax_send(conn->conn_ax)) { | |||
922 | case -1: | |||
923 | if (errno(*__errno()) == EAGAIN35) | |||
924 | break; | |||
925 | log_warn("AgentX(%"PRIu32"u"")", conn->conn_id); | |||
926 | ax_free(conn->conn_ax); | |||
927 | conn->conn_ax = NULL((void *)0); | |||
928 | appl_agentx_free(conn, APPL_CLOSE_REASONOTHER); | |||
929 | return; | |||
930 | case 0: | |||
931 | return; | |||
932 | default: | |||
933 | break; | |||
934 | } | |||
935 | event_add(&(conn->conn_wev), NULL((void *)0)); | |||
936 | } | |||
937 | ||||
938 | struct ber_oid * | |||
939 | appl_agentx_oid2ber_oid(struct ax_oid *aoid, struct ber_oid *boid) | |||
940 | { | |||
941 | size_t i; | |||
942 | ||||
943 | if (aoid->aoi_idlen < BER_MIN_OID_LEN2 || | |||
944 | aoid->aoi_idlen > BER_MAX_OID_LEN128) { | |||
945 | errno(*__errno()) = EINVAL22; | |||
946 | return NULL((void *)0); | |||
947 | } | |||
948 | ||||
949 | ||||
950 | boid->bo_n = aoid->aoi_idlen; | |||
951 | for (i = 0; i < boid->bo_n; i++) | |||
952 | boid->bo_id[i] = aoid->aoi_id[i]; | |||
953 | return boid; | |||
954 | } | |||
955 | ||||
956 | struct ber_element * | |||
957 | appl_agentx_value2ber_element(struct ax_varbind *vb) | |||
958 | { | |||
959 | struct ber_oid oid; | |||
960 | struct ber_element *elm; | |||
961 | ||||
962 | switch (vb->avb_type) { | |||
963 | case AX_DATA_TYPE_INTEGER: | |||
964 | return ober_add_integer(NULL((void *)0), vb->avb_data.avb_int32); | |||
965 | case AX_DATA_TYPE_OCTETSTRING: | |||
966 | return ober_add_nstring(NULL((void *)0), | |||
967 | vb->avb_data.avb_ostring.aos_string, | |||
968 | vb->avb_data.avb_ostring.aos_slen); | |||
969 | case AX_DATA_TYPE_NULL: | |||
970 | return ober_add_null(NULL((void *)0)); | |||
971 | case AX_DATA_TYPE_OID: | |||
972 | if (appl_agentx_oid2ber_oid( | |||
973 | &(vb->avb_data.avb_oid), &oid) == NULL((void *)0)) | |||
974 | return NULL((void *)0); | |||
975 | return ober_add_oid(NULL((void *)0), &oid); | |||
976 | case AX_DATA_TYPE_IPADDRESS: | |||
977 | if ((elm = ober_add_nstring(NULL((void *)0), | |||
978 | vb->avb_data.avb_ostring.aos_string, | |||
979 | vb->avb_data.avb_ostring.aos_slen)) == NULL((void *)0)) | |||
980 | return NULL((void *)0); | |||
981 | ober_set_header(elm, BER_CLASS_APPLICATION0x1, SNMP_T_IPADDR); | |||
982 | return elm; | |||
983 | case AX_DATA_TYPE_COUNTER32: | |||
984 | elm = ober_add_integer(NULL((void *)0), vb->avb_data.avb_uint32); | |||
985 | if (elm == NULL((void *)0)) | |||
986 | return NULL((void *)0); | |||
987 | ober_set_header(elm, BER_CLASS_APPLICATION0x1, SNMP_T_COUNTER32); | |||
988 | return elm; | |||
989 | case AX_DATA_TYPE_GAUGE32: | |||
990 | elm = ober_add_integer(NULL((void *)0), vb->avb_data.avb_uint32); | |||
991 | if (elm == NULL((void *)0)) | |||
992 | return NULL((void *)0); | |||
993 | ober_set_header(elm, BER_CLASS_APPLICATION0x1, SNMP_T_GAUGE32); | |||
994 | return elm; | |||
995 | case AX_DATA_TYPE_TIMETICKS: | |||
996 | elm = ober_add_integer(NULL((void *)0), vb->avb_data.avb_uint32); | |||
997 | if (elm == NULL((void *)0)) | |||
998 | return NULL((void *)0); | |||
999 | ober_set_header(elm, BER_CLASS_APPLICATION0x1, SNMP_T_TIMETICKS); | |||
1000 | return elm; | |||
1001 | case AX_DATA_TYPE_OPAQUE: | |||
1002 | if ((elm = ober_add_nstring(NULL((void *)0), | |||
1003 | vb->avb_data.avb_ostring.aos_string, | |||
1004 | vb->avb_data.avb_ostring.aos_slen)) == NULL((void *)0)) | |||
1005 | return NULL((void *)0); | |||
1006 | ober_set_header(elm, BER_CLASS_APPLICATION0x1, SNMP_T_OPAQUE); | |||
1007 | return elm; | |||
1008 | case AX_DATA_TYPE_COUNTER64: | |||
1009 | elm = ober_add_integer(NULL((void *)0), vb->avb_data.avb_uint64); | |||
1010 | if (elm == NULL((void *)0)) | |||
1011 | return NULL((void *)0); | |||
1012 | ober_set_header(elm, BER_CLASS_APPLICATION0x1, SNMP_T_COUNTER64); | |||
1013 | return elm; | |||
1014 | case AX_DATA_TYPE_NOSUCHOBJECT: | |||
1015 | return appl_exception(APPL_EXC_NOSUCHOBJECT); | |||
1016 | case AX_DATA_TYPE_NOSUCHINSTANCE: | |||
1017 | return appl_exception(APPL_EXC_NOSUCHINSTANCE); | |||
1018 | case AX_DATA_TYPE_ENDOFMIBVIEW: | |||
1019 | return appl_exception(APPL_EXC_ENDOFMIBVIEW); | |||
1020 | default: | |||
1021 | errno(*__errno()) = EINVAL22; | |||
1022 | return NULL((void *)0); | |||
1023 | } | |||
1024 | } | |||
1025 | ||||
1026 | struct ax_ostring * | |||
1027 | appl_agentx_string2ostring(const char *str, struct ax_ostring *ostring) | |||
1028 | { | |||
1029 | if (str == NULL((void *)0)) { | |||
1030 | errno(*__errno()) = 0; | |||
1031 | return NULL((void *)0); | |||
1032 | } | |||
1033 | ||||
1034 | ostring->aos_slen = strlen(str); | |||
1035 | if ((ostring->aos_string = strdup(str)) == NULL((void *)0)) | |||
1036 | return NULL((void *)0); | |||
1037 | return ostring; | |||
1038 | } | |||
1039 | ||||
1040 | int | |||
1041 | appl_agentx_cmp(struct appl_agentx_connection *conn1, | |||
1042 | struct appl_agentx_connection *conn2) | |||
1043 | { | |||
1044 | return conn1->conn_id < conn2->conn_id ? -1 : | |||
1045 | conn1->conn_id > conn2->conn_id; | |||
1046 | } | |||
1047 | ||||
1048 | int | |||
1049 | appl_agentx_session_cmp(struct appl_agentx_session *sess1, | |||
1050 | struct appl_agentx_session *sess2) | |||
1051 | { | |||
1052 | return sess1->sess_id < sess2->sess_id ? -1 : sess1->sess_id > sess2->sess_id; | |||
1053 | } | |||
1054 | ||||
1055 | RB_GENERATE_STATIC(appl_agentx_conns, appl_agentx_connection, conn_entry,__attribute__((__unused__)) static void appl_agentx_conns_RB_INSERT_COLOR (struct appl_agentx_conns *head, struct appl_agentx_connection *elm) { struct appl_agentx_connection *parent, *gparent, *tmp ; while ((parent = (elm)->conn_entry.rbe_parent) && (parent)->conn_entry.rbe_color == 1) { gparent = (parent) ->conn_entry.rbe_parent; if (parent == (gparent)->conn_entry .rbe_left) { tmp = (gparent)->conn_entry.rbe_right; if (tmp && (tmp)->conn_entry.rbe_color == 1) { (tmp)-> conn_entry.rbe_color = 0; do { (parent)->conn_entry.rbe_color = 0; (gparent)->conn_entry.rbe_color = 1; } while (0); elm = gparent; continue; } if ((parent)->conn_entry.rbe_right == elm) { do { (tmp) = (parent)->conn_entry.rbe_right; if (((parent)->conn_entry.rbe_right = (tmp)->conn_entry.rbe_left )) { ((tmp)->conn_entry.rbe_left)->conn_entry.rbe_parent = (parent); } do {} while (0); if (((tmp)->conn_entry.rbe_parent = (parent)->conn_entry.rbe_parent)) { if ((parent) == ((parent )->conn_entry.rbe_parent)->conn_entry.rbe_left) ((parent )->conn_entry.rbe_parent)->conn_entry.rbe_left = (tmp); else ((parent)->conn_entry.rbe_parent)->conn_entry.rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp)->conn_entry .rbe_left = (parent); (parent)->conn_entry.rbe_parent = (tmp ); do {} while (0); if (((tmp)->conn_entry.rbe_parent)) do {} while (0); } while (0); tmp = parent; parent = elm; elm = tmp; } do { (parent)->conn_entry.rbe_color = 0; (gparent) ->conn_entry.rbe_color = 1; } while (0); do { (tmp) = (gparent )->conn_entry.rbe_left; if (((gparent)->conn_entry.rbe_left = (tmp)->conn_entry.rbe_right)) { ((tmp)->conn_entry.rbe_right )->conn_entry.rbe_parent = (gparent); } do {} while (0); if (((tmp)->conn_entry.rbe_parent = (gparent)->conn_entry .rbe_parent)) { if ((gparent) == ((gparent)->conn_entry.rbe_parent )->conn_entry.rbe_left) ((gparent)->conn_entry.rbe_parent )->conn_entry.rbe_left = (tmp); else ((gparent)->conn_entry .rbe_parent)->conn_entry.rbe_right = (tmp); } else (head)-> rbh_root = (tmp); (tmp)->conn_entry.rbe_right = (gparent); (gparent)->conn_entry.rbe_parent = (tmp); do {} while (0) ; if (((tmp)->conn_entry.rbe_parent)) do {} while (0); } while (0); } else { tmp = (gparent)->conn_entry.rbe_left; if (tmp && (tmp)->conn_entry.rbe_color == 1) { (tmp)-> conn_entry.rbe_color = 0; do { (parent)->conn_entry.rbe_color = 0; (gparent)->conn_entry.rbe_color = 1; } while (0); elm = gparent; continue; } if ((parent)->conn_entry.rbe_left == elm) { do { (tmp) = (parent)->conn_entry.rbe_left; if ((( parent)->conn_entry.rbe_left = (tmp)->conn_entry.rbe_right )) { ((tmp)->conn_entry.rbe_right)->conn_entry.rbe_parent = (parent); } do {} while (0); if (((tmp)->conn_entry.rbe_parent = (parent)->conn_entry.rbe_parent)) { if ((parent) == ((parent )->conn_entry.rbe_parent)->conn_entry.rbe_left) ((parent )->conn_entry.rbe_parent)->conn_entry.rbe_left = (tmp); else ((parent)->conn_entry.rbe_parent)->conn_entry.rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp)->conn_entry .rbe_right = (parent); (parent)->conn_entry.rbe_parent = ( tmp); do {} while (0); if (((tmp)->conn_entry.rbe_parent)) do {} while (0); } while (0); tmp = parent; parent = elm; elm = tmp; } do { (parent)->conn_entry.rbe_color = 0; (gparent )->conn_entry.rbe_color = 1; } while (0); do { (tmp) = (gparent )->conn_entry.rbe_right; if (((gparent)->conn_entry.rbe_right = (tmp)->conn_entry.rbe_left)) { ((tmp)->conn_entry.rbe_left )->conn_entry.rbe_parent = (gparent); } do {} while (0); if (((tmp)->conn_entry.rbe_parent = (gparent)->conn_entry .rbe_parent)) { if ((gparent) == ((gparent)->conn_entry.rbe_parent )->conn_entry.rbe_left) ((gparent)->conn_entry.rbe_parent )->conn_entry.rbe_left = (tmp); else ((gparent)->conn_entry .rbe_parent)->conn_entry.rbe_right = (tmp); } else (head)-> rbh_root = (tmp); (tmp)->conn_entry.rbe_left = (gparent); ( gparent)->conn_entry.rbe_parent = (tmp); do {} while (0); if (((tmp)->conn_entry.rbe_parent)) do {} while (0); } while (0); } } (head->rbh_root)->conn_entry.rbe_color = 0; } __attribute__((__unused__)) static void appl_agentx_conns_RB_REMOVE_COLOR (struct appl_agentx_conns *head, struct appl_agentx_connection *parent, struct appl_agentx_connection *elm) { struct appl_agentx_connection *tmp; while ((elm == ((void *)0) || (elm)->conn_entry.rbe_color == 0) && elm != (head)->rbh_root) { if ((parent)-> conn_entry.rbe_left == elm) { tmp = (parent)->conn_entry.rbe_right ; if ((tmp)->conn_entry.rbe_color == 1) { do { (tmp)->conn_entry .rbe_color = 0; (parent)->conn_entry.rbe_color = 1; } while (0); do { (tmp) = (parent)->conn_entry.rbe_right; if (((parent )->conn_entry.rbe_right = (tmp)->conn_entry.rbe_left)) { ((tmp)->conn_entry.rbe_left)->conn_entry.rbe_parent = ( parent); } do {} while (0); if (((tmp)->conn_entry.rbe_parent = (parent)->conn_entry.rbe_parent)) { if ((parent) == ((parent )->conn_entry.rbe_parent)->conn_entry.rbe_left) ((parent )->conn_entry.rbe_parent)->conn_entry.rbe_left = (tmp); else ((parent)->conn_entry.rbe_parent)->conn_entry.rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp)->conn_entry .rbe_left = (parent); (parent)->conn_entry.rbe_parent = (tmp ); do {} while (0); if (((tmp)->conn_entry.rbe_parent)) do {} while (0); } while (0); tmp = (parent)->conn_entry.rbe_right ; } if (((tmp)->conn_entry.rbe_left == ((void *)0) || ((tmp )->conn_entry.rbe_left)->conn_entry.rbe_color == 0) && ((tmp)->conn_entry.rbe_right == ((void *)0) || ((tmp)-> conn_entry.rbe_right)->conn_entry.rbe_color == 0)) { (tmp) ->conn_entry.rbe_color = 1; elm = parent; parent = (elm)-> conn_entry.rbe_parent; } else { if ((tmp)->conn_entry.rbe_right == ((void *)0) || ((tmp)->conn_entry.rbe_right)->conn_entry .rbe_color == 0) { struct appl_agentx_connection *oleft; if ( (oleft = (tmp)->conn_entry.rbe_left)) (oleft)->conn_entry .rbe_color = 0; (tmp)->conn_entry.rbe_color = 1; do { (oleft ) = (tmp)->conn_entry.rbe_left; if (((tmp)->conn_entry. rbe_left = (oleft)->conn_entry.rbe_right)) { ((oleft)-> conn_entry.rbe_right)->conn_entry.rbe_parent = (tmp); } do {} while (0); if (((oleft)->conn_entry.rbe_parent = (tmp) ->conn_entry.rbe_parent)) { if ((tmp) == ((tmp)->conn_entry .rbe_parent)->conn_entry.rbe_left) ((tmp)->conn_entry.rbe_parent )->conn_entry.rbe_left = (oleft); else ((tmp)->conn_entry .rbe_parent)->conn_entry.rbe_right = (oleft); } else (head )->rbh_root = (oleft); (oleft)->conn_entry.rbe_right = ( tmp); (tmp)->conn_entry.rbe_parent = (oleft); do {} while ( 0); if (((oleft)->conn_entry.rbe_parent)) do {} while (0); } while (0); tmp = (parent)->conn_entry.rbe_right; } (tmp )->conn_entry.rbe_color = (parent)->conn_entry.rbe_color ; (parent)->conn_entry.rbe_color = 0; if ((tmp)->conn_entry .rbe_right) ((tmp)->conn_entry.rbe_right)->conn_entry.rbe_color = 0; do { (tmp) = (parent)->conn_entry.rbe_right; if (((parent )->conn_entry.rbe_right = (tmp)->conn_entry.rbe_left)) { ((tmp)->conn_entry.rbe_left)->conn_entry.rbe_parent = ( parent); } do {} while (0); if (((tmp)->conn_entry.rbe_parent = (parent)->conn_entry.rbe_parent)) { if ((parent) == ((parent )->conn_entry.rbe_parent)->conn_entry.rbe_left) ((parent )->conn_entry.rbe_parent)->conn_entry.rbe_left = (tmp); else ((parent)->conn_entry.rbe_parent)->conn_entry.rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp)->conn_entry .rbe_left = (parent); (parent)->conn_entry.rbe_parent = (tmp ); do {} while (0); if (((tmp)->conn_entry.rbe_parent)) do {} while (0); } while (0); elm = (head)->rbh_root; break; } } else { tmp = (parent)->conn_entry.rbe_left; if ((tmp) ->conn_entry.rbe_color == 1) { do { (tmp)->conn_entry.rbe_color = 0; (parent)->conn_entry.rbe_color = 1; } while (0); do { (tmp) = (parent)->conn_entry.rbe_left; if (((parent)-> conn_entry.rbe_left = (tmp)->conn_entry.rbe_right)) { ((tmp )->conn_entry.rbe_right)->conn_entry.rbe_parent = (parent ); } do {} while (0); if (((tmp)->conn_entry.rbe_parent = ( parent)->conn_entry.rbe_parent)) { if ((parent) == ((parent )->conn_entry.rbe_parent)->conn_entry.rbe_left) ((parent )->conn_entry.rbe_parent)->conn_entry.rbe_left = (tmp); else ((parent)->conn_entry.rbe_parent)->conn_entry.rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp)->conn_entry .rbe_right = (parent); (parent)->conn_entry.rbe_parent = ( tmp); do {} while (0); if (((tmp)->conn_entry.rbe_parent)) do {} while (0); } while (0); tmp = (parent)->conn_entry. rbe_left; } if (((tmp)->conn_entry.rbe_left == ((void *)0) || ((tmp)->conn_entry.rbe_left)->conn_entry.rbe_color == 0) && ((tmp)->conn_entry.rbe_right == ((void *)0) || ((tmp)->conn_entry.rbe_right)->conn_entry.rbe_color == 0)) { (tmp)->conn_entry.rbe_color = 1; elm = parent; parent = (elm)->conn_entry.rbe_parent; } else { if ((tmp)->conn_entry .rbe_left == ((void *)0) || ((tmp)->conn_entry.rbe_left)-> conn_entry.rbe_color == 0) { struct appl_agentx_connection *oright ; if ((oright = (tmp)->conn_entry.rbe_right)) (oright)-> conn_entry.rbe_color = 0; (tmp)->conn_entry.rbe_color = 1; do { (oright) = (tmp)->conn_entry.rbe_right; if (((tmp)-> conn_entry.rbe_right = (oright)->conn_entry.rbe_left)) { ( (oright)->conn_entry.rbe_left)->conn_entry.rbe_parent = (tmp); } do {} while (0); if (((oright)->conn_entry.rbe_parent = (tmp)->conn_entry.rbe_parent)) { if ((tmp) == ((tmp)-> conn_entry.rbe_parent)->conn_entry.rbe_left) ((tmp)->conn_entry .rbe_parent)->conn_entry.rbe_left = (oright); else ((tmp)-> conn_entry.rbe_parent)->conn_entry.rbe_right = (oright); } else (head)->rbh_root = (oright); (oright)->conn_entry .rbe_left = (tmp); (tmp)->conn_entry.rbe_parent = (oright) ; do {} while (0); if (((oright)->conn_entry.rbe_parent)) do {} while (0); } while (0); tmp = (parent)->conn_entry.rbe_left ; } (tmp)->conn_entry.rbe_color = (parent)->conn_entry. rbe_color; (parent)->conn_entry.rbe_color = 0; if ((tmp)-> conn_entry.rbe_left) ((tmp)->conn_entry.rbe_left)->conn_entry .rbe_color = 0; do { (tmp) = (parent)->conn_entry.rbe_left ; if (((parent)->conn_entry.rbe_left = (tmp)->conn_entry .rbe_right)) { ((tmp)->conn_entry.rbe_right)->conn_entry .rbe_parent = (parent); } do {} while (0); if (((tmp)->conn_entry .rbe_parent = (parent)->conn_entry.rbe_parent)) { if ((parent ) == ((parent)->conn_entry.rbe_parent)->conn_entry.rbe_left ) ((parent)->conn_entry.rbe_parent)->conn_entry.rbe_left = (tmp); else ((parent)->conn_entry.rbe_parent)->conn_entry .rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp) ->conn_entry.rbe_right = (parent); (parent)->conn_entry .rbe_parent = (tmp); do {} while (0); if (((tmp)->conn_entry .rbe_parent)) do {} while (0); } while (0); elm = (head)-> rbh_root; break; } } } if (elm) (elm)->conn_entry.rbe_color = 0; } __attribute__((__unused__)) static struct appl_agentx_connection * appl_agentx_conns_RB_REMOVE(struct appl_agentx_conns *head , struct appl_agentx_connection *elm) { struct appl_agentx_connection *child, *parent, *old = elm; int color; if ((elm)->conn_entry .rbe_left == ((void *)0)) child = (elm)->conn_entry.rbe_right ; else if ((elm)->conn_entry.rbe_right == ((void *)0)) child = (elm)->conn_entry.rbe_left; else { struct appl_agentx_connection *left; elm = (elm)->conn_entry.rbe_right; while ((left = ( elm)->conn_entry.rbe_left)) elm = left; child = (elm)-> conn_entry.rbe_right; parent = (elm)->conn_entry.rbe_parent ; color = (elm)->conn_entry.rbe_color; if (child) (child)-> conn_entry.rbe_parent = parent; if (parent) { if ((parent)-> conn_entry.rbe_left == elm) (parent)->conn_entry.rbe_left = child; else (parent)->conn_entry.rbe_right = child; do {} while (0); } else (head)->rbh_root = child; if ((elm)-> conn_entry.rbe_parent == old) parent = elm; (elm)->conn_entry = (old)->conn_entry; if ((old)->conn_entry.rbe_parent) { if (((old)->conn_entry.rbe_parent)->conn_entry.rbe_left == old) ((old)->conn_entry.rbe_parent)->conn_entry.rbe_left = elm; else ((old)->conn_entry.rbe_parent)->conn_entry .rbe_right = elm; do {} while (0); } else (head)->rbh_root = elm; ((old)->conn_entry.rbe_left)->conn_entry.rbe_parent = elm; if ((old)->conn_entry.rbe_right) ((old)->conn_entry .rbe_right)->conn_entry.rbe_parent = elm; if (parent) { left = parent; do { do {} while (0); } while ((left = (left)-> conn_entry.rbe_parent)); } goto color; } parent = (elm)->conn_entry .rbe_parent; color = (elm)->conn_entry.rbe_color; if (child ) (child)->conn_entry.rbe_parent = parent; if (parent) { if ((parent)->conn_entry.rbe_left == elm) (parent)->conn_entry .rbe_left = child; else (parent)->conn_entry.rbe_right = child ; do {} while (0); } else (head)->rbh_root = child; color: if (color == 0) appl_agentx_conns_RB_REMOVE_COLOR(head, parent , child); return (old); } __attribute__((__unused__)) static struct appl_agentx_connection * appl_agentx_conns_RB_INSERT(struct appl_agentx_conns *head, struct appl_agentx_connection *elm) { struct appl_agentx_connection *tmp; struct appl_agentx_connection *parent = ((void *)0); int comp = 0; tmp = (head)->rbh_root; while (tmp) { parent = tmp ; comp = (appl_agentx_cmp)(elm, parent); if (comp < 0) tmp = (tmp)->conn_entry.rbe_left; else if (comp > 0) tmp = (tmp)->conn_entry.rbe_right; else return (tmp); } do { (elm )->conn_entry.rbe_parent = parent; (elm)->conn_entry.rbe_left = (elm)->conn_entry.rbe_right = ((void *)0); (elm)->conn_entry .rbe_color = 1; } while (0); if (parent != ((void *)0)) { if ( comp < 0) (parent)->conn_entry.rbe_left = elm; else (parent )->conn_entry.rbe_right = elm; do {} while (0); } else (head )->rbh_root = elm; appl_agentx_conns_RB_INSERT_COLOR(head, elm); return (((void *)0)); } __attribute__((__unused__)) static struct appl_agentx_connection * appl_agentx_conns_RB_FIND(struct appl_agentx_conns *head, struct appl_agentx_connection *elm) { struct appl_agentx_connection *tmp = (head)->rbh_root; int comp; while (tmp) { comp = appl_agentx_cmp(elm, tmp); if (comp < 0) tmp = (tmp)->conn_entry.rbe_left; else if (comp > 0) tmp = (tmp)->conn_entry.rbe_right; else return (tmp); } return (((void *)0)); } __attribute__((__unused__)) static struct appl_agentx_connection * appl_agentx_conns_RB_NFIND(struct appl_agentx_conns *head, struct appl_agentx_connection *elm) { struct appl_agentx_connection *tmp = (head)->rbh_root; struct appl_agentx_connection *res = ((void *)0); int comp; while (tmp) { comp = appl_agentx_cmp (elm, tmp); if (comp < 0) { res = tmp; tmp = (tmp)->conn_entry .rbe_left; } else if (comp > 0) tmp = (tmp)->conn_entry .rbe_right; else return (tmp); } return (res); } __attribute__ ((__unused__)) static struct appl_agentx_connection * appl_agentx_conns_RB_NEXT (struct appl_agentx_connection *elm) { if ((elm)->conn_entry .rbe_right) { elm = (elm)->conn_entry.rbe_right; while ((elm )->conn_entry.rbe_left) elm = (elm)->conn_entry.rbe_left ; } else { if ((elm)->conn_entry.rbe_parent && (elm == ((elm)->conn_entry.rbe_parent)->conn_entry.rbe_left )) elm = (elm)->conn_entry.rbe_parent; else { while ((elm) ->conn_entry.rbe_parent && (elm == ((elm)->conn_entry .rbe_parent)->conn_entry.rbe_right)) elm = (elm)->conn_entry .rbe_parent; elm = (elm)->conn_entry.rbe_parent; } } return (elm); } __attribute__((__unused__)) static struct appl_agentx_connection * appl_agentx_conns_RB_PREV(struct appl_agentx_connection *elm ) { if ((elm)->conn_entry.rbe_left) { elm = (elm)->conn_entry .rbe_left; while ((elm)->conn_entry.rbe_right) elm = (elm) ->conn_entry.rbe_right; } else { if ((elm)->conn_entry. rbe_parent && (elm == ((elm)->conn_entry.rbe_parent )->conn_entry.rbe_right)) elm = (elm)->conn_entry.rbe_parent ; else { while ((elm)->conn_entry.rbe_parent && (elm == ((elm)->conn_entry.rbe_parent)->conn_entry.rbe_left )) elm = (elm)->conn_entry.rbe_parent; elm = (elm)->conn_entry .rbe_parent; } } return (elm); } __attribute__((__unused__)) static struct appl_agentx_connection * appl_agentx_conns_RB_MINMAX( struct appl_agentx_conns *head, int val) { struct appl_agentx_connection *tmp = (head)->rbh_root; struct appl_agentx_connection *parent = ((void *)0); while (tmp) { parent = tmp; if (val < 0) tmp = (tmp)->conn_entry.rbe_left; else tmp = (tmp)->conn_entry .rbe_right; } return (parent); } | |||
1056 | appl_agentx_cmp)__attribute__((__unused__)) static void appl_agentx_conns_RB_INSERT_COLOR (struct appl_agentx_conns *head, struct appl_agentx_connection *elm) { struct appl_agentx_connection *parent, *gparent, *tmp ; while ((parent = (elm)->conn_entry.rbe_parent) && (parent)->conn_entry.rbe_color == 1) { gparent = (parent) ->conn_entry.rbe_parent; if (parent == (gparent)->conn_entry .rbe_left) { tmp = (gparent)->conn_entry.rbe_right; if (tmp && (tmp)->conn_entry.rbe_color == 1) { (tmp)-> conn_entry.rbe_color = 0; do { (parent)->conn_entry.rbe_color = 0; (gparent)->conn_entry.rbe_color = 1; } while (0); elm = gparent; continue; } if ((parent)->conn_entry.rbe_right == elm) { do { (tmp) = (parent)->conn_entry.rbe_right; if (((parent)->conn_entry.rbe_right = (tmp)->conn_entry.rbe_left )) { ((tmp)->conn_entry.rbe_left)->conn_entry.rbe_parent = (parent); } do {} while (0); if (((tmp)->conn_entry.rbe_parent = (parent)->conn_entry.rbe_parent)) { if ((parent) == ((parent )->conn_entry.rbe_parent)->conn_entry.rbe_left) ((parent )->conn_entry.rbe_parent)->conn_entry.rbe_left = (tmp); else ((parent)->conn_entry.rbe_parent)->conn_entry.rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp)->conn_entry .rbe_left = (parent); (parent)->conn_entry.rbe_parent = (tmp ); do {} while (0); if (((tmp)->conn_entry.rbe_parent)) do {} while (0); } while (0); tmp = parent; parent = elm; elm = tmp; } do { (parent)->conn_entry.rbe_color = 0; (gparent) ->conn_entry.rbe_color = 1; } while (0); do { (tmp) = (gparent )->conn_entry.rbe_left; if (((gparent)->conn_entry.rbe_left = (tmp)->conn_entry.rbe_right)) { ((tmp)->conn_entry.rbe_right )->conn_entry.rbe_parent = (gparent); } do {} while (0); if (((tmp)->conn_entry.rbe_parent = (gparent)->conn_entry .rbe_parent)) { if ((gparent) == ((gparent)->conn_entry.rbe_parent )->conn_entry.rbe_left) ((gparent)->conn_entry.rbe_parent )->conn_entry.rbe_left = (tmp); else ((gparent)->conn_entry .rbe_parent)->conn_entry.rbe_right = (tmp); } else (head)-> rbh_root = (tmp); (tmp)->conn_entry.rbe_right = (gparent); (gparent)->conn_entry.rbe_parent = (tmp); do {} while (0) ; if (((tmp)->conn_entry.rbe_parent)) do {} while (0); } while (0); } else { tmp = (gparent)->conn_entry.rbe_left; if (tmp && (tmp)->conn_entry.rbe_color == 1) { (tmp)-> conn_entry.rbe_color = 0; do { (parent)->conn_entry.rbe_color = 0; (gparent)->conn_entry.rbe_color = 1; } while (0); elm = gparent; continue; } if ((parent)->conn_entry.rbe_left == elm) { do { (tmp) = (parent)->conn_entry.rbe_left; if ((( parent)->conn_entry.rbe_left = (tmp)->conn_entry.rbe_right )) { ((tmp)->conn_entry.rbe_right)->conn_entry.rbe_parent = (parent); } do {} while (0); if (((tmp)->conn_entry.rbe_parent = (parent)->conn_entry.rbe_parent)) { if ((parent) == ((parent )->conn_entry.rbe_parent)->conn_entry.rbe_left) ((parent )->conn_entry.rbe_parent)->conn_entry.rbe_left = (tmp); else ((parent)->conn_entry.rbe_parent)->conn_entry.rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp)->conn_entry .rbe_right = (parent); (parent)->conn_entry.rbe_parent = ( tmp); do {} while (0); if (((tmp)->conn_entry.rbe_parent)) do {} while (0); } while (0); tmp = parent; parent = elm; elm = tmp; } do { (parent)->conn_entry.rbe_color = 0; (gparent )->conn_entry.rbe_color = 1; } while (0); do { (tmp) = (gparent )->conn_entry.rbe_right; if (((gparent)->conn_entry.rbe_right = (tmp)->conn_entry.rbe_left)) { ((tmp)->conn_entry.rbe_left )->conn_entry.rbe_parent = (gparent); } do {} while (0); if (((tmp)->conn_entry.rbe_parent = (gparent)->conn_entry .rbe_parent)) { if ((gparent) == ((gparent)->conn_entry.rbe_parent )->conn_entry.rbe_left) ((gparent)->conn_entry.rbe_parent )->conn_entry.rbe_left = (tmp); else ((gparent)->conn_entry .rbe_parent)->conn_entry.rbe_right = (tmp); } else (head)-> rbh_root = (tmp); (tmp)->conn_entry.rbe_left = (gparent); ( gparent)->conn_entry.rbe_parent = (tmp); do {} while (0); if (((tmp)->conn_entry.rbe_parent)) do {} while (0); } while (0); } } (head->rbh_root)->conn_entry.rbe_color = 0; } __attribute__((__unused__)) static void appl_agentx_conns_RB_REMOVE_COLOR (struct appl_agentx_conns *head, struct appl_agentx_connection *parent, struct appl_agentx_connection *elm) { struct appl_agentx_connection *tmp; while ((elm == ((void *)0) || (elm)->conn_entry.rbe_color == 0) && elm != (head)->rbh_root) { if ((parent)-> conn_entry.rbe_left == elm) { tmp = (parent)->conn_entry.rbe_right ; if ((tmp)->conn_entry.rbe_color == 1) { do { (tmp)->conn_entry .rbe_color = 0; (parent)->conn_entry.rbe_color = 1; } while (0); do { (tmp) = (parent)->conn_entry.rbe_right; if (((parent )->conn_entry.rbe_right = (tmp)->conn_entry.rbe_left)) { ((tmp)->conn_entry.rbe_left)->conn_entry.rbe_parent = ( parent); } do {} while (0); if (((tmp)->conn_entry.rbe_parent = (parent)->conn_entry.rbe_parent)) { if ((parent) == ((parent )->conn_entry.rbe_parent)->conn_entry.rbe_left) ((parent )->conn_entry.rbe_parent)->conn_entry.rbe_left = (tmp); else ((parent)->conn_entry.rbe_parent)->conn_entry.rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp)->conn_entry .rbe_left = (parent); (parent)->conn_entry.rbe_parent = (tmp ); do {} while (0); if (((tmp)->conn_entry.rbe_parent)) do {} while (0); } while (0); tmp = (parent)->conn_entry.rbe_right ; } if (((tmp)->conn_entry.rbe_left == ((void *)0) || ((tmp )->conn_entry.rbe_left)->conn_entry.rbe_color == 0) && ((tmp)->conn_entry.rbe_right == ((void *)0) || ((tmp)-> conn_entry.rbe_right)->conn_entry.rbe_color == 0)) { (tmp) ->conn_entry.rbe_color = 1; elm = parent; parent = (elm)-> conn_entry.rbe_parent; } else { if ((tmp)->conn_entry.rbe_right == ((void *)0) || ((tmp)->conn_entry.rbe_right)->conn_entry .rbe_color == 0) { struct appl_agentx_connection *oleft; if ( (oleft = (tmp)->conn_entry.rbe_left)) (oleft)->conn_entry .rbe_color = 0; (tmp)->conn_entry.rbe_color = 1; do { (oleft ) = (tmp)->conn_entry.rbe_left; if (((tmp)->conn_entry. rbe_left = (oleft)->conn_entry.rbe_right)) { ((oleft)-> conn_entry.rbe_right)->conn_entry.rbe_parent = (tmp); } do {} while (0); if (((oleft)->conn_entry.rbe_parent = (tmp) ->conn_entry.rbe_parent)) { if ((tmp) == ((tmp)->conn_entry .rbe_parent)->conn_entry.rbe_left) ((tmp)->conn_entry.rbe_parent )->conn_entry.rbe_left = (oleft); else ((tmp)->conn_entry .rbe_parent)->conn_entry.rbe_right = (oleft); } else (head )->rbh_root = (oleft); (oleft)->conn_entry.rbe_right = ( tmp); (tmp)->conn_entry.rbe_parent = (oleft); do {} while ( 0); if (((oleft)->conn_entry.rbe_parent)) do {} while (0); } while (0); tmp = (parent)->conn_entry.rbe_right; } (tmp )->conn_entry.rbe_color = (parent)->conn_entry.rbe_color ; (parent)->conn_entry.rbe_color = 0; if ((tmp)->conn_entry .rbe_right) ((tmp)->conn_entry.rbe_right)->conn_entry.rbe_color = 0; do { (tmp) = (parent)->conn_entry.rbe_right; if (((parent )->conn_entry.rbe_right = (tmp)->conn_entry.rbe_left)) { ((tmp)->conn_entry.rbe_left)->conn_entry.rbe_parent = ( parent); } do {} while (0); if (((tmp)->conn_entry.rbe_parent = (parent)->conn_entry.rbe_parent)) { if ((parent) == ((parent )->conn_entry.rbe_parent)->conn_entry.rbe_left) ((parent )->conn_entry.rbe_parent)->conn_entry.rbe_left = (tmp); else ((parent)->conn_entry.rbe_parent)->conn_entry.rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp)->conn_entry .rbe_left = (parent); (parent)->conn_entry.rbe_parent = (tmp ); do {} while (0); if (((tmp)->conn_entry.rbe_parent)) do {} while (0); } while (0); elm = (head)->rbh_root; break; } } else { tmp = (parent)->conn_entry.rbe_left; if ((tmp) ->conn_entry.rbe_color == 1) { do { (tmp)->conn_entry.rbe_color = 0; (parent)->conn_entry.rbe_color = 1; } while (0); do { (tmp) = (parent)->conn_entry.rbe_left; if (((parent)-> conn_entry.rbe_left = (tmp)->conn_entry.rbe_right)) { ((tmp )->conn_entry.rbe_right)->conn_entry.rbe_parent = (parent ); } do {} while (0); if (((tmp)->conn_entry.rbe_parent = ( parent)->conn_entry.rbe_parent)) { if ((parent) == ((parent )->conn_entry.rbe_parent)->conn_entry.rbe_left) ((parent )->conn_entry.rbe_parent)->conn_entry.rbe_left = (tmp); else ((parent)->conn_entry.rbe_parent)->conn_entry.rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp)->conn_entry .rbe_right = (parent); (parent)->conn_entry.rbe_parent = ( tmp); do {} while (0); if (((tmp)->conn_entry.rbe_parent)) do {} while (0); } while (0); tmp = (parent)->conn_entry. rbe_left; } if (((tmp)->conn_entry.rbe_left == ((void *)0) || ((tmp)->conn_entry.rbe_left)->conn_entry.rbe_color == 0) && ((tmp)->conn_entry.rbe_right == ((void *)0) || ((tmp)->conn_entry.rbe_right)->conn_entry.rbe_color == 0)) { (tmp)->conn_entry.rbe_color = 1; elm = parent; parent = (elm)->conn_entry.rbe_parent; } else { if ((tmp)->conn_entry .rbe_left == ((void *)0) || ((tmp)->conn_entry.rbe_left)-> conn_entry.rbe_color == 0) { struct appl_agentx_connection *oright ; if ((oright = (tmp)->conn_entry.rbe_right)) (oright)-> conn_entry.rbe_color = 0; (tmp)->conn_entry.rbe_color = 1; do { (oright) = (tmp)->conn_entry.rbe_right; if (((tmp)-> conn_entry.rbe_right = (oright)->conn_entry.rbe_left)) { ( (oright)->conn_entry.rbe_left)->conn_entry.rbe_parent = (tmp); } do {} while (0); if (((oright)->conn_entry.rbe_parent = (tmp)->conn_entry.rbe_parent)) { if ((tmp) == ((tmp)-> conn_entry.rbe_parent)->conn_entry.rbe_left) ((tmp)->conn_entry .rbe_parent)->conn_entry.rbe_left = (oright); else ((tmp)-> conn_entry.rbe_parent)->conn_entry.rbe_right = (oright); } else (head)->rbh_root = (oright); (oright)->conn_entry .rbe_left = (tmp); (tmp)->conn_entry.rbe_parent = (oright) ; do {} while (0); if (((oright)->conn_entry.rbe_parent)) do {} while (0); } while (0); tmp = (parent)->conn_entry.rbe_left ; } (tmp)->conn_entry.rbe_color = (parent)->conn_entry. rbe_color; (parent)->conn_entry.rbe_color = 0; if ((tmp)-> conn_entry.rbe_left) ((tmp)->conn_entry.rbe_left)->conn_entry .rbe_color = 0; do { (tmp) = (parent)->conn_entry.rbe_left ; if (((parent)->conn_entry.rbe_left = (tmp)->conn_entry .rbe_right)) { ((tmp)->conn_entry.rbe_right)->conn_entry .rbe_parent = (parent); } do {} while (0); if (((tmp)->conn_entry .rbe_parent = (parent)->conn_entry.rbe_parent)) { if ((parent ) == ((parent)->conn_entry.rbe_parent)->conn_entry.rbe_left ) ((parent)->conn_entry.rbe_parent)->conn_entry.rbe_left = (tmp); else ((parent)->conn_entry.rbe_parent)->conn_entry .rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp) ->conn_entry.rbe_right = (parent); (parent)->conn_entry .rbe_parent = (tmp); do {} while (0); if (((tmp)->conn_entry .rbe_parent)) do {} while (0); } while (0); elm = (head)-> rbh_root; break; } } } if (elm) (elm)->conn_entry.rbe_color = 0; } __attribute__((__unused__)) static struct appl_agentx_connection * appl_agentx_conns_RB_REMOVE(struct appl_agentx_conns *head , struct appl_agentx_connection *elm) { struct appl_agentx_connection *child, *parent, *old = elm; int color; if ((elm)->conn_entry .rbe_left == ((void *)0)) child = (elm)->conn_entry.rbe_right ; else if ((elm)->conn_entry.rbe_right == ((void *)0)) child = (elm)->conn_entry.rbe_left; else { struct appl_agentx_connection *left; elm = (elm)->conn_entry.rbe_right; while ((left = ( elm)->conn_entry.rbe_left)) elm = left; child = (elm)-> conn_entry.rbe_right; parent = (elm)->conn_entry.rbe_parent ; color = (elm)->conn_entry.rbe_color; if (child) (child)-> conn_entry.rbe_parent = parent; if (parent) { if ((parent)-> conn_entry.rbe_left == elm) (parent)->conn_entry.rbe_left = child; else (parent)->conn_entry.rbe_right = child; do {} while (0); } else (head)->rbh_root = child; if ((elm)-> conn_entry.rbe_parent == old) parent = elm; (elm)->conn_entry = (old)->conn_entry; if ((old)->conn_entry.rbe_parent) { if (((old)->conn_entry.rbe_parent)->conn_entry.rbe_left == old) ((old)->conn_entry.rbe_parent)->conn_entry.rbe_left = elm; else ((old)->conn_entry.rbe_parent)->conn_entry .rbe_right = elm; do {} while (0); } else (head)->rbh_root = elm; ((old)->conn_entry.rbe_left)->conn_entry.rbe_parent = elm; if ((old)->conn_entry.rbe_right) ((old)->conn_entry .rbe_right)->conn_entry.rbe_parent = elm; if (parent) { left = parent; do { do {} while (0); } while ((left = (left)-> conn_entry.rbe_parent)); } goto color; } parent = (elm)->conn_entry .rbe_parent; color = (elm)->conn_entry.rbe_color; if (child ) (child)->conn_entry.rbe_parent = parent; if (parent) { if ((parent)->conn_entry.rbe_left == elm) (parent)->conn_entry .rbe_left = child; else (parent)->conn_entry.rbe_right = child ; do {} while (0); } else (head)->rbh_root = child; color: if (color == 0) appl_agentx_conns_RB_REMOVE_COLOR(head, parent , child); return (old); } __attribute__((__unused__)) static struct appl_agentx_connection * appl_agentx_conns_RB_INSERT(struct appl_agentx_conns *head, struct appl_agentx_connection *elm) { struct appl_agentx_connection *tmp; struct appl_agentx_connection *parent = ((void *)0); int comp = 0; tmp = (head)->rbh_root; while (tmp) { parent = tmp ; comp = (appl_agentx_cmp)(elm, parent); if (comp < 0) tmp = (tmp)->conn_entry.rbe_left; else if (comp > 0) tmp = (tmp)->conn_entry.rbe_right; else return (tmp); } do { (elm )->conn_entry.rbe_parent = parent; (elm)->conn_entry.rbe_left = (elm)->conn_entry.rbe_right = ((void *)0); (elm)->conn_entry .rbe_color = 1; } while (0); if (parent != ((void *)0)) { if ( comp < 0) (parent)->conn_entry.rbe_left = elm; else (parent )->conn_entry.rbe_right = elm; do {} while (0); } else (head )->rbh_root = elm; appl_agentx_conns_RB_INSERT_COLOR(head, elm); return (((void *)0)); } __attribute__((__unused__)) static struct appl_agentx_connection * appl_agentx_conns_RB_FIND(struct appl_agentx_conns *head, struct appl_agentx_connection *elm) { struct appl_agentx_connection *tmp = (head)->rbh_root; int comp; while (tmp) { comp = appl_agentx_cmp(elm, tmp); if (comp < 0) tmp = (tmp)->conn_entry.rbe_left; else if (comp > 0) tmp = (tmp)->conn_entry.rbe_right; else return (tmp); } return (((void *)0)); } __attribute__((__unused__)) static struct appl_agentx_connection * appl_agentx_conns_RB_NFIND(struct appl_agentx_conns *head, struct appl_agentx_connection *elm) { struct appl_agentx_connection *tmp = (head)->rbh_root; struct appl_agentx_connection *res = ((void *)0); int comp; while (tmp) { comp = appl_agentx_cmp (elm, tmp); if (comp < 0) { res = tmp; tmp = (tmp)->conn_entry .rbe_left; } else if (comp > 0) tmp = (tmp)->conn_entry .rbe_right; else return (tmp); } return (res); } __attribute__ ((__unused__)) static struct appl_agentx_connection * appl_agentx_conns_RB_NEXT (struct appl_agentx_connection *elm) { if ((elm)->conn_entry .rbe_right) { elm = (elm)->conn_entry.rbe_right; while ((elm )->conn_entry.rbe_left) elm = (elm)->conn_entry.rbe_left ; } else { if ((elm)->conn_entry.rbe_parent && (elm == ((elm)->conn_entry.rbe_parent)->conn_entry.rbe_left )) elm = (elm)->conn_entry.rbe_parent; else { while ((elm) ->conn_entry.rbe_parent && (elm == ((elm)->conn_entry .rbe_parent)->conn_entry.rbe_right)) elm = (elm)->conn_entry .rbe_parent; elm = (elm)->conn_entry.rbe_parent; } } return (elm); } __attribute__((__unused__)) static struct appl_agentx_connection * appl_agentx_conns_RB_PREV(struct appl_agentx_connection *elm ) { if ((elm)->conn_entry.rbe_left) { elm = (elm)->conn_entry .rbe_left; while ((elm)->conn_entry.rbe_right) elm = (elm) ->conn_entry.rbe_right; } else { if ((elm)->conn_entry. rbe_parent && (elm == ((elm)->conn_entry.rbe_parent )->conn_entry.rbe_right)) elm = (elm)->conn_entry.rbe_parent ; else { while ((elm)->conn_entry.rbe_parent && (elm == ((elm)->conn_entry.rbe_parent)->conn_entry.rbe_left )) elm = (elm)->conn_entry.rbe_parent; elm = (elm)->conn_entry .rbe_parent; } } return (elm); } __attribute__((__unused__)) static struct appl_agentx_connection * appl_agentx_conns_RB_MINMAX( struct appl_agentx_conns *head, int val) { struct appl_agentx_connection *tmp = (head)->rbh_root; struct appl_agentx_connection *parent = ((void *)0); while (tmp) { parent = tmp; if (val < 0) tmp = (tmp)->conn_entry.rbe_left; else tmp = (tmp)->conn_entry .rbe_right; } return (parent); }; | |||
1057 | RB_GENERATE_STATIC(appl_agentx_sessions, appl_agentx_session, sess_entry,__attribute__((__unused__)) static void appl_agentx_sessions_RB_INSERT_COLOR (struct appl_agentx_sessions *head, struct appl_agentx_session *elm) { struct appl_agentx_session *parent, *gparent, *tmp; while ((parent = (elm)->sess_entry.rbe_parent) && (parent )->sess_entry.rbe_color == 1) { gparent = (parent)->sess_entry .rbe_parent; if (parent == (gparent)->sess_entry.rbe_left) { tmp = (gparent)->sess_entry.rbe_right; if (tmp && (tmp)->sess_entry.rbe_color == 1) { (tmp)->sess_entry. rbe_color = 0; do { (parent)->sess_entry.rbe_color = 0; (gparent )->sess_entry.rbe_color = 1; } while (0); elm = gparent; continue ; } if ((parent)->sess_entry.rbe_right == elm) { do { (tmp ) = (parent)->sess_entry.rbe_right; if (((parent)->sess_entry .rbe_right = (tmp)->sess_entry.rbe_left)) { ((tmp)->sess_entry .rbe_left)->sess_entry.rbe_parent = (parent); } do {} while (0); if (((tmp)->sess_entry.rbe_parent = (parent)->sess_entry .rbe_parent)) { if ((parent) == ((parent)->sess_entry.rbe_parent )->sess_entry.rbe_left) ((parent)->sess_entry.rbe_parent )->sess_entry.rbe_left = (tmp); else ((parent)->sess_entry .rbe_parent)->sess_entry.rbe_right = (tmp); } else (head)-> rbh_root = (tmp); (tmp)->sess_entry.rbe_left = (parent); ( parent)->sess_entry.rbe_parent = (tmp); do {} while (0); if (((tmp)->sess_entry.rbe_parent)) do {} while (0); } while (0); tmp = parent; parent = elm; elm = tmp; } do { (parent)-> sess_entry.rbe_color = 0; (gparent)->sess_entry.rbe_color = 1; } while (0); do { (tmp) = (gparent)->sess_entry.rbe_left ; if (((gparent)->sess_entry.rbe_left = (tmp)->sess_entry .rbe_right)) { ((tmp)->sess_entry.rbe_right)->sess_entry .rbe_parent = (gparent); } do {} while (0); if (((tmp)->sess_entry .rbe_parent = (gparent)->sess_entry.rbe_parent)) { if ((gparent ) == ((gparent)->sess_entry.rbe_parent)->sess_entry.rbe_left ) ((gparent)->sess_entry.rbe_parent)->sess_entry.rbe_left = (tmp); else ((gparent)->sess_entry.rbe_parent)->sess_entry .rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp) ->sess_entry.rbe_right = (gparent); (gparent)->sess_entry .rbe_parent = (tmp); do {} while (0); if (((tmp)->sess_entry .rbe_parent)) do {} while (0); } while (0); } else { tmp = (gparent )->sess_entry.rbe_left; if (tmp && (tmp)->sess_entry .rbe_color == 1) { (tmp)->sess_entry.rbe_color = 0; do { ( parent)->sess_entry.rbe_color = 0; (gparent)->sess_entry .rbe_color = 1; } while (0); elm = gparent; continue; } if (( parent)->sess_entry.rbe_left == elm) { do { (tmp) = (parent )->sess_entry.rbe_left; if (((parent)->sess_entry.rbe_left = (tmp)->sess_entry.rbe_right)) { ((tmp)->sess_entry.rbe_right )->sess_entry.rbe_parent = (parent); } do {} while (0); if (((tmp)->sess_entry.rbe_parent = (parent)->sess_entry. rbe_parent)) { if ((parent) == ((parent)->sess_entry.rbe_parent )->sess_entry.rbe_left) ((parent)->sess_entry.rbe_parent )->sess_entry.rbe_left = (tmp); else ((parent)->sess_entry .rbe_parent)->sess_entry.rbe_right = (tmp); } else (head)-> rbh_root = (tmp); (tmp)->sess_entry.rbe_right = (parent); ( parent)->sess_entry.rbe_parent = (tmp); do {} while (0); if (((tmp)->sess_entry.rbe_parent)) do {} while (0); } while (0); tmp = parent; parent = elm; elm = tmp; } do { (parent)-> sess_entry.rbe_color = 0; (gparent)->sess_entry.rbe_color = 1; } while (0); do { (tmp) = (gparent)->sess_entry.rbe_right ; if (((gparent)->sess_entry.rbe_right = (tmp)->sess_entry .rbe_left)) { ((tmp)->sess_entry.rbe_left)->sess_entry. rbe_parent = (gparent); } do {} while (0); if (((tmp)->sess_entry .rbe_parent = (gparent)->sess_entry.rbe_parent)) { if ((gparent ) == ((gparent)->sess_entry.rbe_parent)->sess_entry.rbe_left ) ((gparent)->sess_entry.rbe_parent)->sess_entry.rbe_left = (tmp); else ((gparent)->sess_entry.rbe_parent)->sess_entry .rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp) ->sess_entry.rbe_left = (gparent); (gparent)->sess_entry .rbe_parent = (tmp); do {} while (0); if (((tmp)->sess_entry .rbe_parent)) do {} while (0); } while (0); } } (head->rbh_root )->sess_entry.rbe_color = 0; } __attribute__((__unused__)) static void appl_agentx_sessions_RB_REMOVE_COLOR(struct appl_agentx_sessions *head, struct appl_agentx_session *parent, struct appl_agentx_session *elm) { struct appl_agentx_session *tmp; while ((elm == ((void *)0) || (elm)->sess_entry.rbe_color == 0) && elm != (head)->rbh_root) { if ((parent)->sess_entry.rbe_left == elm) { tmp = (parent)->sess_entry.rbe_right; if ((tmp)-> sess_entry.rbe_color == 1) { do { (tmp)->sess_entry.rbe_color = 0; (parent)->sess_entry.rbe_color = 1; } while (0); do { (tmp) = (parent)->sess_entry.rbe_right; if (((parent)-> sess_entry.rbe_right = (tmp)->sess_entry.rbe_left)) { ((tmp )->sess_entry.rbe_left)->sess_entry.rbe_parent = (parent ); } do {} while (0); if (((tmp)->sess_entry.rbe_parent = ( parent)->sess_entry.rbe_parent)) { if ((parent) == ((parent )->sess_entry.rbe_parent)->sess_entry.rbe_left) ((parent )->sess_entry.rbe_parent)->sess_entry.rbe_left = (tmp); else ((parent)->sess_entry.rbe_parent)->sess_entry.rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp)->sess_entry .rbe_left = (parent); (parent)->sess_entry.rbe_parent = (tmp ); do {} while (0); if (((tmp)->sess_entry.rbe_parent)) do {} while (0); } while (0); tmp = (parent)->sess_entry.rbe_right ; } if (((tmp)->sess_entry.rbe_left == ((void *)0) || ((tmp )->sess_entry.rbe_left)->sess_entry.rbe_color == 0) && ((tmp)->sess_entry.rbe_right == ((void *)0) || ((tmp)-> sess_entry.rbe_right)->sess_entry.rbe_color == 0)) { (tmp) ->sess_entry.rbe_color = 1; elm = parent; parent = (elm)-> sess_entry.rbe_parent; } else { if ((tmp)->sess_entry.rbe_right == ((void *)0) || ((tmp)->sess_entry.rbe_right)->sess_entry .rbe_color == 0) { struct appl_agentx_session *oleft; if ((oleft = (tmp)->sess_entry.rbe_left)) (oleft)->sess_entry.rbe_color = 0; (tmp)->sess_entry.rbe_color = 1; do { (oleft) = (tmp )->sess_entry.rbe_left; if (((tmp)->sess_entry.rbe_left = (oleft)->sess_entry.rbe_right)) { ((oleft)->sess_entry .rbe_right)->sess_entry.rbe_parent = (tmp); } do {} while ( 0); if (((oleft)->sess_entry.rbe_parent = (tmp)->sess_entry .rbe_parent)) { if ((tmp) == ((tmp)->sess_entry.rbe_parent )->sess_entry.rbe_left) ((tmp)->sess_entry.rbe_parent)-> sess_entry.rbe_left = (oleft); else ((tmp)->sess_entry.rbe_parent )->sess_entry.rbe_right = (oleft); } else (head)->rbh_root = (oleft); (oleft)->sess_entry.rbe_right = (tmp); (tmp)-> sess_entry.rbe_parent = (oleft); do {} while (0); if (((oleft )->sess_entry.rbe_parent)) do {} while (0); } while (0); tmp = (parent)->sess_entry.rbe_right; } (tmp)->sess_entry. rbe_color = (parent)->sess_entry.rbe_color; (parent)->sess_entry .rbe_color = 0; if ((tmp)->sess_entry.rbe_right) ((tmp)-> sess_entry.rbe_right)->sess_entry.rbe_color = 0; do { (tmp ) = (parent)->sess_entry.rbe_right; if (((parent)->sess_entry .rbe_right = (tmp)->sess_entry.rbe_left)) { ((tmp)->sess_entry .rbe_left)->sess_entry.rbe_parent = (parent); } do {} while (0); if (((tmp)->sess_entry.rbe_parent = (parent)->sess_entry .rbe_parent)) { if ((parent) == ((parent)->sess_entry.rbe_parent )->sess_entry.rbe_left) ((parent)->sess_entry.rbe_parent )->sess_entry.rbe_left = (tmp); else ((parent)->sess_entry .rbe_parent)->sess_entry.rbe_right = (tmp); } else (head)-> rbh_root = (tmp); (tmp)->sess_entry.rbe_left = (parent); ( parent)->sess_entry.rbe_parent = (tmp); do {} while (0); if (((tmp)->sess_entry.rbe_parent)) do {} while (0); } while (0); elm = (head)->rbh_root; break; } } else { tmp = (parent )->sess_entry.rbe_left; if ((tmp)->sess_entry.rbe_color == 1) { do { (tmp)->sess_entry.rbe_color = 0; (parent)-> sess_entry.rbe_color = 1; } while (0); do { (tmp) = (parent)-> sess_entry.rbe_left; if (((parent)->sess_entry.rbe_left = ( tmp)->sess_entry.rbe_right)) { ((tmp)->sess_entry.rbe_right )->sess_entry.rbe_parent = (parent); } do {} while (0); if (((tmp)->sess_entry.rbe_parent = (parent)->sess_entry. rbe_parent)) { if ((parent) == ((parent)->sess_entry.rbe_parent )->sess_entry.rbe_left) ((parent)->sess_entry.rbe_parent )->sess_entry.rbe_left = (tmp); else ((parent)->sess_entry .rbe_parent)->sess_entry.rbe_right = (tmp); } else (head)-> rbh_root = (tmp); (tmp)->sess_entry.rbe_right = (parent); ( parent)->sess_entry.rbe_parent = (tmp); do {} while (0); if (((tmp)->sess_entry.rbe_parent)) do {} while (0); } while (0); tmp = (parent)->sess_entry.rbe_left; } if (((tmp)-> sess_entry.rbe_left == ((void *)0) || ((tmp)->sess_entry.rbe_left )->sess_entry.rbe_color == 0) && ((tmp)->sess_entry .rbe_right == ((void *)0) || ((tmp)->sess_entry.rbe_right) ->sess_entry.rbe_color == 0)) { (tmp)->sess_entry.rbe_color = 1; elm = parent; parent = (elm)->sess_entry.rbe_parent; } else { if ((tmp)->sess_entry.rbe_left == ((void *)0) || ((tmp)->sess_entry.rbe_left)->sess_entry.rbe_color == 0 ) { struct appl_agentx_session *oright; if ((oright = (tmp)-> sess_entry.rbe_right)) (oright)->sess_entry.rbe_color = 0; (tmp)->sess_entry.rbe_color = 1; do { (oright) = (tmp)-> sess_entry.rbe_right; if (((tmp)->sess_entry.rbe_right = ( oright)->sess_entry.rbe_left)) { ((oright)->sess_entry. rbe_left)->sess_entry.rbe_parent = (tmp); } do {} while (0 ); if (((oright)->sess_entry.rbe_parent = (tmp)->sess_entry .rbe_parent)) { if ((tmp) == ((tmp)->sess_entry.rbe_parent )->sess_entry.rbe_left) ((tmp)->sess_entry.rbe_parent)-> sess_entry.rbe_left = (oright); else ((tmp)->sess_entry.rbe_parent )->sess_entry.rbe_right = (oright); } else (head)->rbh_root = (oright); (oright)->sess_entry.rbe_left = (tmp); (tmp)-> sess_entry.rbe_parent = (oright); do {} while (0); if (((oright )->sess_entry.rbe_parent)) do {} while (0); } while (0); tmp = (parent)->sess_entry.rbe_left; } (tmp)->sess_entry.rbe_color = (parent)->sess_entry.rbe_color; (parent)->sess_entry .rbe_color = 0; if ((tmp)->sess_entry.rbe_left) ((tmp)-> sess_entry.rbe_left)->sess_entry.rbe_color = 0; do { (tmp) = (parent)->sess_entry.rbe_left; if (((parent)->sess_entry .rbe_left = (tmp)->sess_entry.rbe_right)) { ((tmp)->sess_entry .rbe_right)->sess_entry.rbe_parent = (parent); } do {} while (0); if (((tmp)->sess_entry.rbe_parent = (parent)->sess_entry .rbe_parent)) { if ((parent) == ((parent)->sess_entry.rbe_parent )->sess_entry.rbe_left) ((parent)->sess_entry.rbe_parent )->sess_entry.rbe_left = (tmp); else ((parent)->sess_entry .rbe_parent)->sess_entry.rbe_right = (tmp); } else (head)-> rbh_root = (tmp); (tmp)->sess_entry.rbe_right = (parent); ( parent)->sess_entry.rbe_parent = (tmp); do {} while (0); if (((tmp)->sess_entry.rbe_parent)) do {} while (0); } while (0); elm = (head)->rbh_root; break; } } } if (elm) (elm)-> sess_entry.rbe_color = 0; } __attribute__((__unused__)) static struct appl_agentx_session * appl_agentx_sessions_RB_REMOVE( struct appl_agentx_sessions *head, struct appl_agentx_session *elm) { struct appl_agentx_session *child, *parent, *old = elm ; int color; if ((elm)->sess_entry.rbe_left == ((void *)0) ) child = (elm)->sess_entry.rbe_right; else if ((elm)-> sess_entry.rbe_right == ((void *)0)) child = (elm)->sess_entry .rbe_left; else { struct appl_agentx_session *left; elm = (elm )->sess_entry.rbe_right; while ((left = (elm)->sess_entry .rbe_left)) elm = left; child = (elm)->sess_entry.rbe_right ; parent = (elm)->sess_entry.rbe_parent; color = (elm)-> sess_entry.rbe_color; if (child) (child)->sess_entry.rbe_parent = parent; if (parent) { if ((parent)->sess_entry.rbe_left == elm) (parent)->sess_entry.rbe_left = child; else (parent )->sess_entry.rbe_right = child; do {} while (0); } else ( head)->rbh_root = child; if ((elm)->sess_entry.rbe_parent == old) parent = elm; (elm)->sess_entry = (old)->sess_entry ; if ((old)->sess_entry.rbe_parent) { if (((old)->sess_entry .rbe_parent)->sess_entry.rbe_left == old) ((old)->sess_entry .rbe_parent)->sess_entry.rbe_left = elm; else ((old)->sess_entry .rbe_parent)->sess_entry.rbe_right = elm; do {} while (0); } else (head)->rbh_root = elm; ((old)->sess_entry.rbe_left )->sess_entry.rbe_parent = elm; if ((old)->sess_entry.rbe_right ) ((old)->sess_entry.rbe_right)->sess_entry.rbe_parent = elm; if (parent) { left = parent; do { do {} while (0); } while ((left = (left)->sess_entry.rbe_parent)); } goto color; } parent = (elm)->sess_entry.rbe_parent; color = (elm)-> sess_entry.rbe_color; if (child) (child)->sess_entry.rbe_parent = parent; if (parent) { if ((parent)->sess_entry.rbe_left == elm) (parent)->sess_entry.rbe_left = child; else (parent )->sess_entry.rbe_right = child; do {} while (0); } else ( head)->rbh_root = child; color: if (color == 0) appl_agentx_sessions_RB_REMOVE_COLOR (head, parent, child); return (old); } __attribute__((__unused__ )) static struct appl_agentx_session * appl_agentx_sessions_RB_INSERT (struct appl_agentx_sessions *head, struct appl_agentx_session *elm) { struct appl_agentx_session *tmp; struct appl_agentx_session *parent = ((void *)0); int comp = 0; tmp = (head)->rbh_root ; while (tmp) { parent = tmp; comp = (appl_agentx_session_cmp )(elm, parent); if (comp < 0) tmp = (tmp)->sess_entry.rbe_left ; else if (comp > 0) tmp = (tmp)->sess_entry.rbe_right; else return (tmp); } do { (elm)->sess_entry.rbe_parent = parent ; (elm)->sess_entry.rbe_left = (elm)->sess_entry.rbe_right = ((void *)0); (elm)->sess_entry.rbe_color = 1; } while ( 0); if (parent != ((void *)0)) { if (comp < 0) (parent)-> sess_entry.rbe_left = elm; else (parent)->sess_entry.rbe_right = elm; do {} while (0); } else (head)->rbh_root = elm; appl_agentx_sessions_RB_INSERT_COLOR (head, elm); return (((void *)0)); } __attribute__((__unused__ )) static struct appl_agentx_session * appl_agentx_sessions_RB_FIND (struct appl_agentx_sessions *head, struct appl_agentx_session *elm) { struct appl_agentx_session *tmp = (head)->rbh_root ; int comp; while (tmp) { comp = appl_agentx_session_cmp(elm, tmp); if (comp < 0) tmp = (tmp)->sess_entry.rbe_left; else if (comp > 0) tmp = (tmp)->sess_entry.rbe_right; else return (tmp); } return (((void *)0)); } __attribute__((__unused__)) static struct appl_agentx_session * appl_agentx_sessions_RB_NFIND (struct appl_agentx_sessions *head, struct appl_agentx_session *elm) { struct appl_agentx_session *tmp = (head)->rbh_root ; struct appl_agentx_session *res = ((void *)0); int comp; while (tmp) { comp = appl_agentx_session_cmp(elm, tmp); if (comp < 0) { res = tmp; tmp = (tmp)->sess_entry.rbe_left; } else if (comp > 0) tmp = (tmp)->sess_entry.rbe_right; else return (tmp); } return (res); } __attribute__((__unused__)) static struct appl_agentx_session * appl_agentx_sessions_RB_NEXT(struct appl_agentx_session *elm) { if ((elm)->sess_entry.rbe_right) { elm = (elm)-> sess_entry.rbe_right; while ((elm)->sess_entry.rbe_left) elm = (elm)->sess_entry.rbe_left; } else { if ((elm)->sess_entry .rbe_parent && (elm == ((elm)->sess_entry.rbe_parent )->sess_entry.rbe_left)) elm = (elm)->sess_entry.rbe_parent ; else { while ((elm)->sess_entry.rbe_parent && (elm == ((elm)->sess_entry.rbe_parent)->sess_entry.rbe_right )) elm = (elm)->sess_entry.rbe_parent; elm = (elm)->sess_entry .rbe_parent; } } return (elm); } __attribute__((__unused__)) static struct appl_agentx_session * appl_agentx_sessions_RB_PREV(struct appl_agentx_session *elm) { if ((elm)->sess_entry.rbe_left ) { elm = (elm)->sess_entry.rbe_left; while ((elm)->sess_entry .rbe_right) elm = (elm)->sess_entry.rbe_right; } else { if ((elm)->sess_entry.rbe_parent && (elm == ((elm)-> sess_entry.rbe_parent)->sess_entry.rbe_right)) elm = (elm) ->sess_entry.rbe_parent; else { while ((elm)->sess_entry .rbe_parent && (elm == ((elm)->sess_entry.rbe_parent )->sess_entry.rbe_left)) elm = (elm)->sess_entry.rbe_parent ; elm = (elm)->sess_entry.rbe_parent; } } return (elm); } __attribute__ ((__unused__)) static struct appl_agentx_session * appl_agentx_sessions_RB_MINMAX (struct appl_agentx_sessions *head, int val) { struct appl_agentx_session *tmp = (head)->rbh_root; struct appl_agentx_session *parent = ((void *)0); while (tmp) { parent = tmp; if (val < 0) tmp = (tmp)->sess_entry.rbe_left; else tmp = (tmp)->sess_entry .rbe_right; } return (parent); } | |||
1058 | appl_agentx_session_cmp)__attribute__((__unused__)) static void appl_agentx_sessions_RB_INSERT_COLOR (struct appl_agentx_sessions *head, struct appl_agentx_session *elm) { struct appl_agentx_session *parent, *gparent, *tmp; while ((parent = (elm)->sess_entry.rbe_parent) && (parent )->sess_entry.rbe_color == 1) { gparent = (parent)->sess_entry .rbe_parent; if (parent == (gparent)->sess_entry.rbe_left) { tmp = (gparent)->sess_entry.rbe_right; if (tmp && (tmp)->sess_entry.rbe_color == 1) { (tmp)->sess_entry. rbe_color = 0; do { (parent)->sess_entry.rbe_color = 0; (gparent )->sess_entry.rbe_color = 1; } while (0); elm = gparent; continue ; } if ((parent)->sess_entry.rbe_right == elm) { do { (tmp ) = (parent)->sess_entry.rbe_right; if (((parent)->sess_entry .rbe_right = (tmp)->sess_entry.rbe_left)) { ((tmp)->sess_entry .rbe_left)->sess_entry.rbe_parent = (parent); } do {} while (0); if (((tmp)->sess_entry.rbe_parent = (parent)->sess_entry .rbe_parent)) { if ((parent) == ((parent)->sess_entry.rbe_parent )->sess_entry.rbe_left) ((parent)->sess_entry.rbe_parent )->sess_entry.rbe_left = (tmp); else ((parent)->sess_entry .rbe_parent)->sess_entry.rbe_right = (tmp); } else (head)-> rbh_root = (tmp); (tmp)->sess_entry.rbe_left = (parent); ( parent)->sess_entry.rbe_parent = (tmp); do {} while (0); if (((tmp)->sess_entry.rbe_parent)) do {} while (0); } while (0); tmp = parent; parent = elm; elm = tmp; } do { (parent)-> sess_entry.rbe_color = 0; (gparent)->sess_entry.rbe_color = 1; } while (0); do { (tmp) = (gparent)->sess_entry.rbe_left ; if (((gparent)->sess_entry.rbe_left = (tmp)->sess_entry .rbe_right)) { ((tmp)->sess_entry.rbe_right)->sess_entry .rbe_parent = (gparent); } do {} while (0); if (((tmp)->sess_entry .rbe_parent = (gparent)->sess_entry.rbe_parent)) { if ((gparent ) == ((gparent)->sess_entry.rbe_parent)->sess_entry.rbe_left ) ((gparent)->sess_entry.rbe_parent)->sess_entry.rbe_left = (tmp); else ((gparent)->sess_entry.rbe_parent)->sess_entry .rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp) ->sess_entry.rbe_right = (gparent); (gparent)->sess_entry .rbe_parent = (tmp); do {} while (0); if (((tmp)->sess_entry .rbe_parent)) do {} while (0); } while (0); } else { tmp = (gparent )->sess_entry.rbe_left; if (tmp && (tmp)->sess_entry .rbe_color == 1) { (tmp)->sess_entry.rbe_color = 0; do { ( parent)->sess_entry.rbe_color = 0; (gparent)->sess_entry .rbe_color = 1; } while (0); elm = gparent; continue; } if (( parent)->sess_entry.rbe_left == elm) { do { (tmp) = (parent )->sess_entry.rbe_left; if (((parent)->sess_entry.rbe_left = (tmp)->sess_entry.rbe_right)) { ((tmp)->sess_entry.rbe_right )->sess_entry.rbe_parent = (parent); } do {} while (0); if (((tmp)->sess_entry.rbe_parent = (parent)->sess_entry. rbe_parent)) { if ((parent) == ((parent)->sess_entry.rbe_parent )->sess_entry.rbe_left) ((parent)->sess_entry.rbe_parent )->sess_entry.rbe_left = (tmp); else ((parent)->sess_entry .rbe_parent)->sess_entry.rbe_right = (tmp); } else (head)-> rbh_root = (tmp); (tmp)->sess_entry.rbe_right = (parent); ( parent)->sess_entry.rbe_parent = (tmp); do {} while (0); if (((tmp)->sess_entry.rbe_parent)) do {} while (0); } while (0); tmp = parent; parent = elm; elm = tmp; } do { (parent)-> sess_entry.rbe_color = 0; (gparent)->sess_entry.rbe_color = 1; } while (0); do { (tmp) = (gparent)->sess_entry.rbe_right ; if (((gparent)->sess_entry.rbe_right = (tmp)->sess_entry .rbe_left)) { ((tmp)->sess_entry.rbe_left)->sess_entry. rbe_parent = (gparent); } do {} while (0); if (((tmp)->sess_entry .rbe_parent = (gparent)->sess_entry.rbe_parent)) { if ((gparent ) == ((gparent)->sess_entry.rbe_parent)->sess_entry.rbe_left ) ((gparent)->sess_entry.rbe_parent)->sess_entry.rbe_left = (tmp); else ((gparent)->sess_entry.rbe_parent)->sess_entry .rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp) ->sess_entry.rbe_left = (gparent); (gparent)->sess_entry .rbe_parent = (tmp); do {} while (0); if (((tmp)->sess_entry .rbe_parent)) do {} while (0); } while (0); } } (head->rbh_root )->sess_entry.rbe_color = 0; } __attribute__((__unused__)) static void appl_agentx_sessions_RB_REMOVE_COLOR(struct appl_agentx_sessions *head, struct appl_agentx_session *parent, struct appl_agentx_session *elm) { struct appl_agentx_session *tmp; while ((elm == ((void *)0) || (elm)->sess_entry.rbe_color == 0) && elm != (head)->rbh_root) { if ((parent)->sess_entry.rbe_left == elm) { tmp = (parent)->sess_entry.rbe_right; if ((tmp)-> sess_entry.rbe_color == 1) { do { (tmp)->sess_entry.rbe_color = 0; (parent)->sess_entry.rbe_color = 1; } while (0); do { (tmp) = (parent)->sess_entry.rbe_right; if (((parent)-> sess_entry.rbe_right = (tmp)->sess_entry.rbe_left)) { ((tmp )->sess_entry.rbe_left)->sess_entry.rbe_parent = (parent ); } do {} while (0); if (((tmp)->sess_entry.rbe_parent = ( parent)->sess_entry.rbe_parent)) { if ((parent) == ((parent )->sess_entry.rbe_parent)->sess_entry.rbe_left) ((parent )->sess_entry.rbe_parent)->sess_entry.rbe_left = (tmp); else ((parent)->sess_entry.rbe_parent)->sess_entry.rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp)->sess_entry .rbe_left = (parent); (parent)->sess_entry.rbe_parent = (tmp ); do {} while (0); if (((tmp)->sess_entry.rbe_parent)) do {} while (0); } while (0); tmp = (parent)->sess_entry.rbe_right ; } if (((tmp)->sess_entry.rbe_left == ((void *)0) || ((tmp )->sess_entry.rbe_left)->sess_entry.rbe_color == 0) && ((tmp)->sess_entry.rbe_right == ((void *)0) || ((tmp)-> sess_entry.rbe_right)->sess_entry.rbe_color == 0)) { (tmp) ->sess_entry.rbe_color = 1; elm = parent; parent = (elm)-> sess_entry.rbe_parent; } else { if ((tmp)->sess_entry.rbe_right == ((void *)0) || ((tmp)->sess_entry.rbe_right)->sess_entry .rbe_color == 0) { struct appl_agentx_session *oleft; if ((oleft = (tmp)->sess_entry.rbe_left)) (oleft)->sess_entry.rbe_color = 0; (tmp)->sess_entry.rbe_color = 1; do { (oleft) = (tmp )->sess_entry.rbe_left; if (((tmp)->sess_entry.rbe_left = (oleft)->sess_entry.rbe_right)) { ((oleft)->sess_entry .rbe_right)->sess_entry.rbe_parent = (tmp); } do {} while ( 0); if (((oleft)->sess_entry.rbe_parent = (tmp)->sess_entry .rbe_parent)) { if ((tmp) == ((tmp)->sess_entry.rbe_parent )->sess_entry.rbe_left) ((tmp)->sess_entry.rbe_parent)-> sess_entry.rbe_left = (oleft); else ((tmp)->sess_entry.rbe_parent )->sess_entry.rbe_right = (oleft); } else (head)->rbh_root = (oleft); (oleft)->sess_entry.rbe_right = (tmp); (tmp)-> sess_entry.rbe_parent = (oleft); do {} while (0); if (((oleft )->sess_entry.rbe_parent)) do {} while (0); } while (0); tmp = (parent)->sess_entry.rbe_right; } (tmp)->sess_entry. rbe_color = (parent)->sess_entry.rbe_color; (parent)->sess_entry .rbe_color = 0; if ((tmp)->sess_entry.rbe_right) ((tmp)-> sess_entry.rbe_right)->sess_entry.rbe_color = 0; do { (tmp ) = (parent)->sess_entry.rbe_right; if (((parent)->sess_entry .rbe_right = (tmp)->sess_entry.rbe_left)) { ((tmp)->sess_entry .rbe_left)->sess_entry.rbe_parent = (parent); } do {} while (0); if (((tmp)->sess_entry.rbe_parent = (parent)->sess_entry .rbe_parent)) { if ((parent) == ((parent)->sess_entry.rbe_parent )->sess_entry.rbe_left) ((parent)->sess_entry.rbe_parent )->sess_entry.rbe_left = (tmp); else ((parent)->sess_entry .rbe_parent)->sess_entry.rbe_right = (tmp); } else (head)-> rbh_root = (tmp); (tmp)->sess_entry.rbe_left = (parent); ( parent)->sess_entry.rbe_parent = (tmp); do {} while (0); if (((tmp)->sess_entry.rbe_parent)) do {} while (0); } while (0); elm = (head)->rbh_root; break; } } else { tmp = (parent )->sess_entry.rbe_left; if ((tmp)->sess_entry.rbe_color == 1) { do { (tmp)->sess_entry.rbe_color = 0; (parent)-> sess_entry.rbe_color = 1; } while (0); do { (tmp) = (parent)-> sess_entry.rbe_left; if (((parent)->sess_entry.rbe_left = ( tmp)->sess_entry.rbe_right)) { ((tmp)->sess_entry.rbe_right )->sess_entry.rbe_parent = (parent); } do {} while (0); if (((tmp)->sess_entry.rbe_parent = (parent)->sess_entry. rbe_parent)) { if ((parent) == ((parent)->sess_entry.rbe_parent )->sess_entry.rbe_left) ((parent)->sess_entry.rbe_parent )->sess_entry.rbe_left = (tmp); else ((parent)->sess_entry .rbe_parent)->sess_entry.rbe_right = (tmp); } else (head)-> rbh_root = (tmp); (tmp)->sess_entry.rbe_right = (parent); ( parent)->sess_entry.rbe_parent = (tmp); do {} while (0); if (((tmp)->sess_entry.rbe_parent)) do {} while (0); } while (0); tmp = (parent)->sess_entry.rbe_left; } if (((tmp)-> sess_entry.rbe_left == ((void *)0) || ((tmp)->sess_entry.rbe_left )->sess_entry.rbe_color == 0) && ((tmp)->sess_entry .rbe_right == ((void *)0) || ((tmp)->sess_entry.rbe_right) ->sess_entry.rbe_color == 0)) { (tmp)->sess_entry.rbe_color = 1; elm = parent; parent = (elm)->sess_entry.rbe_parent; } else { if ((tmp)->sess_entry.rbe_left == ((void *)0) || ((tmp)->sess_entry.rbe_left)->sess_entry.rbe_color == 0 ) { struct appl_agentx_session *oright; if ((oright = (tmp)-> sess_entry.rbe_right)) (oright)->sess_entry.rbe_color = 0; (tmp)->sess_entry.rbe_color = 1; do { (oright) = (tmp)-> sess_entry.rbe_right; if (((tmp)->sess_entry.rbe_right = ( oright)->sess_entry.rbe_left)) { ((oright)->sess_entry. rbe_left)->sess_entry.rbe_parent = (tmp); } do {} while (0 ); if (((oright)->sess_entry.rbe_parent = (tmp)->sess_entry .rbe_parent)) { if ((tmp) == ((tmp)->sess_entry.rbe_parent )->sess_entry.rbe_left) ((tmp)->sess_entry.rbe_parent)-> sess_entry.rbe_left = (oright); else ((tmp)->sess_entry.rbe_parent )->sess_entry.rbe_right = (oright); } else (head)->rbh_root = (oright); (oright)->sess_entry.rbe_left = (tmp); (tmp)-> sess_entry.rbe_parent = (oright); do {} while (0); if (((oright )->sess_entry.rbe_parent)) do {} while (0); } while (0); tmp = (parent)->sess_entry.rbe_left; } (tmp)->sess_entry.rbe_color = (parent)->sess_entry.rbe_color; (parent)->sess_entry .rbe_color = 0; if ((tmp)->sess_entry.rbe_left) ((tmp)-> sess_entry.rbe_left)->sess_entry.rbe_color = 0; do { (tmp) = (parent)->sess_entry.rbe_left; if (((parent)->sess_entry .rbe_left = (tmp)->sess_entry.rbe_right)) { ((tmp)->sess_entry .rbe_right)->sess_entry.rbe_parent = (parent); } do {} while (0); if (((tmp)->sess_entry.rbe_parent = (parent)->sess_entry .rbe_parent)) { if ((parent) == ((parent)->sess_entry.rbe_parent )->sess_entry.rbe_left) ((parent)->sess_entry.rbe_parent )->sess_entry.rbe_left = (tmp); else ((parent)->sess_entry .rbe_parent)->sess_entry.rbe_right = (tmp); } else (head)-> rbh_root = (tmp); (tmp)->sess_entry.rbe_right = (parent); ( parent)->sess_entry.rbe_parent = (tmp); do {} while (0); if (((tmp)->sess_entry.rbe_parent)) do {} while (0); } while (0); elm = (head)->rbh_root; break; } } } if (elm) (elm)-> sess_entry.rbe_color = 0; } __attribute__((__unused__)) static struct appl_agentx_session * appl_agentx_sessions_RB_REMOVE( struct appl_agentx_sessions *head, struct appl_agentx_session *elm) { struct appl_agentx_session *child, *parent, *old = elm ; int color; if ((elm)->sess_entry.rbe_left == ((void *)0) ) child = (elm)->sess_entry.rbe_right; else if ((elm)-> sess_entry.rbe_right == ((void *)0)) child = (elm)->sess_entry .rbe_left; else { struct appl_agentx_session *left; elm = (elm )->sess_entry.rbe_right; while ((left = (elm)->sess_entry .rbe_left)) elm = left; child = (elm)->sess_entry.rbe_right ; parent = (elm)->sess_entry.rbe_parent; color = (elm)-> sess_entry.rbe_color; if (child) (child)->sess_entry.rbe_parent = parent; if (parent) { if ((parent)->sess_entry.rbe_left == elm) (parent)->sess_entry.rbe_left = child; else (parent )->sess_entry.rbe_right = child; do {} while (0); } else ( head)->rbh_root = child; if ((elm)->sess_entry.rbe_parent == old) parent = elm; (elm)->sess_entry = (old)->sess_entry ; if ((old)->sess_entry.rbe_parent) { if (((old)->sess_entry .rbe_parent)->sess_entry.rbe_left == old) ((old)->sess_entry .rbe_parent)->sess_entry.rbe_left = elm; else ((old)->sess_entry .rbe_parent)->sess_entry.rbe_right = elm; do {} while (0); } else (head)->rbh_root = elm; ((old)->sess_entry.rbe_left )->sess_entry.rbe_parent = elm; if ((old)->sess_entry.rbe_right ) ((old)->sess_entry.rbe_right)->sess_entry.rbe_parent = elm; if (parent) { left = parent; do { do {} while (0); } while ((left = (left)->sess_entry.rbe_parent)); } goto color; } parent = (elm)->sess_entry.rbe_parent; color = (elm)-> sess_entry.rbe_color; if (child) (child)->sess_entry.rbe_parent = parent; if (parent) { if ((parent)->sess_entry.rbe_left == elm) (parent)->sess_entry.rbe_left = child; else (parent )->sess_entry.rbe_right = child; do {} while (0); } else ( head)->rbh_root = child; color: if (color == 0) appl_agentx_sessions_RB_REMOVE_COLOR (head, parent, child); return (old); } __attribute__((__unused__ )) static struct appl_agentx_session * appl_agentx_sessions_RB_INSERT (struct appl_agentx_sessions *head, struct appl_agentx_session *elm) { struct appl_agentx_session *tmp; struct appl_agentx_session *parent = ((void *)0); int comp = 0; tmp = (head)->rbh_root ; while (tmp) { parent = tmp; comp = (appl_agentx_session_cmp )(elm, parent); if (comp < 0) tmp = (tmp)->sess_entry.rbe_left ; else if (comp > 0) tmp = (tmp)->sess_entry.rbe_right; else return (tmp); } do { (elm)->sess_entry.rbe_parent = parent ; (elm)->sess_entry.rbe_left = (elm)->sess_entry.rbe_right = ((void *)0); (elm)->sess_entry.rbe_color = 1; } while ( 0); if (parent != ((void *)0)) { if (comp < 0) (parent)-> sess_entry.rbe_left = elm; else (parent)->sess_entry.rbe_right = elm; do {} while (0); } else (head)->rbh_root = elm; appl_agentx_sessions_RB_INSERT_COLOR (head, elm); return (((void *)0)); } __attribute__((__unused__ )) static struct appl_agentx_session * appl_agentx_sessions_RB_FIND (struct appl_agentx_sessions *head, struct appl_agentx_session *elm) { struct appl_agentx_session *tmp = (head)->rbh_root ; int comp; while (tmp) { comp = appl_agentx_session_cmp(elm, tmp); if (comp < 0) tmp = (tmp)->sess_entry.rbe_left; else if (comp > 0) tmp = (tmp)->sess_entry.rbe_right; else return (tmp); } return (((void *)0)); } __attribute__((__unused__)) static struct appl_agentx_session * appl_agentx_sessions_RB_NFIND (struct appl_agentx_sessions *head, struct appl_agentx_session *elm) { struct appl_agentx_session *tmp = (head)->rbh_root ; struct appl_agentx_session *res = ((void *)0); int comp; while (tmp) { comp = appl_agentx_session_cmp(elm, tmp); if (comp < 0) { res = tmp; tmp = (tmp)->sess_entry.rbe_left; } else if (comp > 0) tmp = (tmp)->sess_entry.rbe_right; else return (tmp); } return (res); } __attribute__((__unused__)) static struct appl_agentx_session * appl_agentx_sessions_RB_NEXT(struct appl_agentx_session *elm) { if ((elm)->sess_entry.rbe_right) { elm = (elm)-> sess_entry.rbe_right; while ((elm)->sess_entry.rbe_left) elm = (elm)->sess_entry.rbe_left; } else { if ((elm)->sess_entry .rbe_parent && (elm == ((elm)->sess_entry.rbe_parent )->sess_entry.rbe_left)) elm = (elm)->sess_entry.rbe_parent ; else { while ((elm)->sess_entry.rbe_parent && (elm == ((elm)->sess_entry.rbe_parent)->sess_entry.rbe_right )) elm = (elm)->sess_entry.rbe_parent; elm = (elm)->sess_entry .rbe_parent; } } return (elm); } __attribute__((__unused__)) static struct appl_agentx_session * appl_agentx_sessions_RB_PREV(struct appl_agentx_session *elm) { if ((elm)->sess_entry.rbe_left ) { elm = (elm)->sess_entry.rbe_left; while ((elm)->sess_entry .rbe_right) elm = (elm)->sess_entry.rbe_right; } else { if ((elm)->sess_entry.rbe_parent && (elm == ((elm)-> sess_entry.rbe_parent)->sess_entry.rbe_right)) elm = (elm) ->sess_entry.rbe_parent; else { while ((elm)->sess_entry .rbe_parent && (elm == ((elm)->sess_entry.rbe_parent )->sess_entry.rbe_left)) elm = (elm)->sess_entry.rbe_parent ; elm = (elm)->sess_entry.rbe_parent; } } return (elm); } __attribute__ ((__unused__)) static struct appl_agentx_session * appl_agentx_sessions_RB_MINMAX (struct appl_agentx_sessions *head, int val) { struct appl_agentx_session *tmp = (head)->rbh_root; struct appl_agentx_session *parent = ((void *)0); while (tmp) { parent = tmp; if (val < 0) tmp = (tmp)->sess_entry.rbe_left; else tmp = (tmp)->sess_entry .rbe_right; } return (parent); }; |