Bug Summary

File:src/usr.sbin/hostapd/hostapd.c
Warning:line 408, column 2
Value stored to 'argv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name hostapd.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/hostapd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/hostapd -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/hostapd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/hostapd/hostapd.c
1/* $OpenBSD: hostapd.c,v 1.41 2019/07/03 03:24:03 deraadt Exp $ */
2
3/*
4 * Copyright (c) 2004, 2005 Reyk Floeter <reyk@openbsd.org>
5 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include <sys/ioctl.h>
21#include <sys/types.h>
22#include <sys/signal.h>
23#include <sys/socket.h>
24#include <sys/time.h>
25#include <sys/queue.h>
26#include <sys/stat.h>
27
28#include <net/if.h>
29#include <net/if_media.h>
30#include <net/if_arp.h>
31#include <net/if_llc.h>
32#include <net/bpf.h>
33
34#include <netinet/in.h>
35#include <netinet/if_ether.h>
36#include <arpa/inet.h>
37
38#include <errno(*__errno()).h>
39#include <event.h>
40#include <fcntl.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <stdarg.h>
44#include <string.h>
45#include <unistd.h>
46#include <limits.h>
47#include <err.h>
48
49#include "hostapd.h"
50#include "iapp.h"
51
52void hostapd_usage(void);
53void hostapd_udp_init(struct hostapd_config *);
54void hostapd_sig_handler(int, short, void *);
55static __inline int
56 hostapd_entry_cmp(struct hostapd_entry *, struct hostapd_entry *);
57
58struct hostapd_config hostapd_cfg;
59
60extern char *__progname;
61char printbuf[BUFSIZ1024];
62
63void
64hostapd_usage(void)
65{
66 fprintf(stderr(&__sF[2]), "usage: %s [-dv] [-D macro=value] [-f file]\n",
67 __progname);
68 exit(EXIT_FAILURE1);
69}
70
71void
72hostapd_log(u_int level, const char *fmt, ...)
73{
74 char *nfmt = NULL((void *)0);
75 va_list ap;
76
77 if (level > hostapd_cfg.c_verbose)
78 return;
79
80 va_start(ap, fmt)__builtin_va_start(ap, fmt);
81 if (hostapd_cfg.c_debug) {
82 if (asprintf(&nfmt, "%s\n", fmt) != -1)
83 vfprintf(stderr(&__sF[2]), nfmt, ap);
84 else {
85 vfprintf(stderr(&__sF[2]), fmt, ap);
86 fprintf(stderr(&__sF[2]), "\n");
87 }
88 fflush(stderr(&__sF[2]));
89 } else
90 vsyslog(LOG_INFO6, fmt, ap);
91 va_end(ap)__builtin_va_end(ap);
92
93 free(nfmt);
94}
95
96void
97hostapd_printf(const char *fmt, ...)
98{
99 char newfmt[BUFSIZ1024];
100 va_list ap;
101 size_t n;
102
103 if (fmt == NULL((void *)0))
104 goto flush;
105
106 va_start(ap, fmt)__builtin_va_start(ap, fmt);
107 bzero(newfmt, sizeof(newfmt));
108 if ((n = strlcpy(newfmt, printbuf, sizeof(newfmt))) >= sizeof(newfmt))
109 goto va_flush;
110 if (strlcpy(newfmt + n, fmt, sizeof(newfmt) - n) >= sizeof(newfmt) - n)
111 goto va_flush;
112 if (vsnprintf(printbuf, sizeof(printbuf), newfmt, ap) < 0)
113 goto va_flush;
114 va_end(ap)__builtin_va_end(ap);
115
116 return;
117
118 va_flush:
119 va_end(ap)__builtin_va_end(ap);
120 flush:
121 if (strlen(printbuf))
122 hostapd_log(HOSTAPD_LOG0, "%s", printbuf);
123 bzero(printbuf, sizeof(printbuf));
124}
125
126void
127hostapd_fatal(const char *fmt, ...)
128{
129 va_list ap;
130
131 va_start(ap, fmt)__builtin_va_start(ap, fmt);
132 if (hostapd_cfg.c_debug) {
133 vfprintf(stderr(&__sF[2]), fmt, ap);
134 fflush(stderr(&__sF[2]));
135 } else
136 vsyslog(LOG_ERR3, fmt, ap);
137 va_end(ap)__builtin_va_end(ap);
138
139 hostapd_cleanup(&hostapd_cfg);
140 exit(EXIT_FAILURE1);
141}
142
143int
144hostapd_check_file_secrecy(int fd, const char *fname)
145{
146 struct stat st;
147
148 if (fstat(fd, &st)) {
149 hostapd_log(HOSTAPD_LOG0,
150 "cannot stat %s", fname);
151 return (-1);
152 }
153
154 if (st.st_uid != 0 && st.st_uid != getuid()) {
155 hostapd_log(HOSTAPD_LOG0,
156 "%s: owner not root or current user", fname);
157 return (-1);
158 }
159
160 if (st.st_mode & (S_IRWXG0000070 | S_IRWXO0000007)) {
161 hostapd_log(HOSTAPD_LOG0,
162 "%s: group/world readable/writeable", fname);
163 return (-1);
164 }
165
166 return (0);
167}
168
169int
170hostapd_bpf_open(u_int flags)
171{
172 int fd = -1;
173 struct bpf_version bpv;
174
175 if ((fd = open("/dev/bpf", flags)) == -1) {
176 hostapd_fatal("unable to open BPF device: %s\n",
177 strerror(errno(*__errno())));
178 }
179
180 /*
181 * Get and validate the BPF version
182 */
183
184 if (ioctl(fd, BIOCVERSION((unsigned long)0x40000000 | ((sizeof(struct bpf_version) &
0x1fff) << 16) | ((('B')) << 8) | ((113)))
, &bpv) == -1)
185 hostapd_fatal("failed to get BPF version: %s\n",
186 strerror(errno(*__errno())));
187
188 if (bpv.bv_major != BPF_MAJOR_VERSION1 ||
189 bpv.bv_minor < BPF_MINOR_VERSION1)
190 hostapd_fatal("invalid BPF version\n");
191
192 return (fd);
193}
194
195void
196hostapd_udp_init(struct hostapd_config *cfg)
197{
198 struct hostapd_iapp *iapp = &cfg->c_iapp;
199 struct ifreq ifr;
200 struct sockaddr_in *addr, baddr;
201 struct ip_mreq mreq;
202 int brd = 1;
203
204 bzero(&ifr, sizeof(ifr));
205
206 /*
207 * Open a listening UDP socket
208 */
209
210 if ((iapp->i_udp = socket(AF_INET2, SOCK_DGRAM2, 0)) == -1)
211 hostapd_fatal("unable to open udp socket\n");
212
213 cfg->c_flags |= HOSTAPD_CFG_F_UDP0x10;
214
215 (void)strlcpy(ifr.ifr_name, iapp->i_iface, sizeof(ifr.ifr_name));
216
217 if (ioctl(iapp->i_udp, SIOCGIFADDR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((33)))
, &ifr) == -1)
218 hostapd_fatal("UDP ioctl %s on \"%s\" failed: %s\n",
219 "SIOCGIFADDR", ifr.ifr_name, strerror(errno(*__errno())));
220
221 addr = (struct sockaddr_in *)&ifr.ifr_addrifr_ifru.ifru_addr;
222 iapp->i_addr.sin_family = AF_INET2;
223 iapp->i_addr.sin_addr.s_addr = addr->sin_addr.s_addr;
224 if (iapp->i_addr.sin_port == 0)
225 iapp->i_addr.sin_port = htons(IAPP_PORT)(__uint16_t)(__builtin_constant_p(3517) ? (__uint16_t)(((__uint16_t
)(3517) & 0xffU) << 8 | ((__uint16_t)(3517) & 0xff00U
) >> 8) : __swap16md(3517))
;
226
227 if (ioctl(iapp->i_udp, SIOCGIFBRDADDR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((35)))
, &ifr) == -1)
228 hostapd_fatal("UDP ioctl %s on \"%s\" failed: %s\n",
229 "SIOCGIFBRDADDR", ifr.ifr_name, strerror(errno(*__errno())));
230
231 addr = (struct sockaddr_in *)&ifr.ifr_addrifr_ifru.ifru_addr;
232 iapp->i_broadcast.sin_family = AF_INET2;
233 iapp->i_broadcast.sin_addr.s_addr = addr->sin_addr.s_addr;
234 iapp->i_broadcast.sin_port = iapp->i_addr.sin_port;
235
236 baddr.sin_family = AF_INET2;
237 baddr.sin_addr.s_addr = htonl(INADDR_ANY)(__uint32_t)(__builtin_constant_p(((u_int32_t)(0x00000000))) ?
(__uint32_t)(((__uint32_t)(((u_int32_t)(0x00000000))) & 0xff
) << 24 | ((__uint32_t)(((u_int32_t)(0x00000000))) &
0xff00) << 8 | ((__uint32_t)(((u_int32_t)(0x00000000))
) & 0xff0000) >> 8 | ((__uint32_t)(((u_int32_t)(0x00000000
))) & 0xff000000) >> 24) : __swap32md(((u_int32_t)(
0x00000000))))
;
238 baddr.sin_port = iapp->i_addr.sin_port;
239
240 if (bind(iapp->i_udp, (struct sockaddr *)&baddr,
241 sizeof(baddr)) == -1)
242 hostapd_fatal("failed to bind UDP socket: %s\n",
243 strerror(errno(*__errno())));
244
245 /*
246 * The revised 802.11F standard requires IAPP messages to be
247 * sent via multicast to the default group 224.0.1.178.
248 * Nevertheless, some implementations still use broadcasts
249 * for IAPP messages.
250 */
251 if (cfg->c_flags & HOSTAPD_CFG_F_BRDCAST0x20) {
252 /*
253 * Enable broadcast
254 */
255 if (setsockopt(iapp->i_udp, SOL_SOCKET0xffff, SO_BROADCAST0x0020,
256 &brd, sizeof(brd)) == -1)
257 hostapd_fatal("failed to enable broadcast on socket\n");
258
259 hostapd_log(HOSTAPD_LOG_DEBUG2, "%s: using broadcast mode "
260 "(address %s)", iapp->i_iface, inet_ntoa(addr->sin_addr));
261 } else {
262 /*
263 * Enable multicast
264 */
265 bzero(&mreq, sizeof(mreq));
266
267 iapp->i_multicast.sin_family = AF_INET2;
268 if (iapp->i_multicast.sin_addr.s_addr == INADDR_ANY((u_int32_t)(0x00000000)))
269 iapp->i_multicast.sin_addr.s_addr =
270 inet_addr(IAPP_MCASTADDR"224.0.1.178");
271 iapp->i_multicast.sin_port = iapp->i_addr.sin_port;
272
273 mreq.imr_multiaddr.s_addr =
274 iapp->i_multicast.sin_addr.s_addr;
275 mreq.imr_interface.s_addr =
276 iapp->i_addr.sin_addr.s_addr;
277
278 if (setsockopt(iapp->i_udp, IPPROTO_IP0,
279 IP_ADD_MEMBERSHIP12, &mreq, sizeof(mreq)) == -1)
280 hostapd_fatal("failed to add multicast membership to "
281 "%s: %s\n", IAPP_MCASTADDR"224.0.1.178", strerror(errno(*__errno())));
282
283 if (setsockopt(iapp->i_udp, IPPROTO_IP0, IP_MULTICAST_TTL10,
284 &iapp->i_ttl, sizeof(iapp->i_ttl)) == -1)
285 hostapd_fatal("failed to set multicast ttl to "
286 "%u: %s\n", iapp->i_ttl, strerror(errno(*__errno())));
287
288 hostapd_log(HOSTAPD_LOG_DEBUG2, "%s: using multicast mode "
289 "(ttl %u, group %s)", iapp->i_iface, iapp->i_ttl,
290 inet_ntoa(iapp->i_multicast.sin_addr));
291 }
292}
293
294/* ARGSUSED */
295void
296hostapd_sig_handler(int sig, short event, void *arg)
297{
298 switch (sig) {
299 case SIGALRM14:
300 case SIGTERM15:
301 case SIGQUIT3:
302 case SIGINT2:
303 (void)event_loopexit(NULL((void *)0));
304 }
305}
306
307void
308hostapd_cleanup(struct hostapd_config *cfg)
309{
310 struct hostapd_iapp *iapp = &cfg->c_iapp;
311 struct ip_mreq mreq;
312 struct hostapd_apme *apme;
313 struct hostapd_table *table;
314 struct hostapd_entry *entry;
315
316 /* Release all Host APs */
317 if (cfg->c_flags & HOSTAPD_CFG_F_APME0x01) {
318 while ((apme = TAILQ_FIRST(&cfg->c_apmes)((&cfg->c_apmes)->tqh_first)) != NULL((void *)0))
319 hostapd_apme_term(apme);
320 }
321
322 if (cfg->c_flags & HOSTAPD_CFG_F_PRIV0x40 &&
323 (cfg->c_flags & HOSTAPD_CFG_F_BRDCAST0x20) == 0) {
324 /*
325 * Disable multicast and let the kernel unsubscribe
326 * from the multicast group.
327 */
328
329 bzero(&mreq, sizeof(mreq));
330
331 mreq.imr_multiaddr.s_addr =
332 inet_addr(IAPP_MCASTADDR"224.0.1.178");
333 mreq.imr_interface.s_addr =
334 iapp->i_addr.sin_addr.s_addr;
335
336 if (setsockopt(iapp->i_udp, IPPROTO_IP0,
337 IP_DROP_MEMBERSHIP13, &mreq, sizeof(mreq)) == -1)
338 hostapd_log(HOSTAPD_LOG0, "failed to remove multicast"
339 " membership to %s: %s",
340 IAPP_MCASTADDR"224.0.1.178", strerror(errno(*__errno())));
341 }
342
343 if ((cfg->c_flags & HOSTAPD_CFG_F_PRIV0x40) == 0 &&
344 cfg->c_flags & HOSTAPD_CFG_F_APME0x01) {
345 /* Shutdown the Host AP protocol handler */
346 hostapd_iapp_term(&hostapd_cfg);
347 }
348
349 /* Cleanup tables */
350 while ((table = TAILQ_FIRST(&cfg->c_tables)((&cfg->c_tables)->tqh_first)) != NULL((void *)0)) {
351 while ((entry = RB_MIN(hostapd_tree, &table->t_tree)hostapd_tree_RB_MINMAX(&table->t_tree, -1)) != NULL((void *)0)) {
352 RB_REMOVE(hostapd_tree, &table->t_tree, entry)hostapd_tree_RB_REMOVE(&table->t_tree, entry);
353 free(entry);
354 }
355 while ((entry = TAILQ_FIRST(&table->t_mask_head)((&table->t_mask_head)->tqh_first)) != NULL((void *)0)) {
356 TAILQ_REMOVE(&table->t_mask_head, entry, e_entries)do { if (((entry)->e_entries.tqe_next) != ((void *)0)) (entry
)->e_entries.tqe_next->e_entries.tqe_prev = (entry)->
e_entries.tqe_prev; else (&table->t_mask_head)->tqh_last
= (entry)->e_entries.tqe_prev; *(entry)->e_entries.tqe_prev
= (entry)->e_entries.tqe_next; ; ; } while (0)
;
357 free(entry);
358 }
359 TAILQ_REMOVE(&cfg->c_tables, table, t_entries)do { if (((table)->t_entries.tqe_next) != ((void *)0)) (table
)->t_entries.tqe_next->t_entries.tqe_prev = (table)->
t_entries.tqe_prev; else (&cfg->c_tables)->tqh_last
= (table)->t_entries.tqe_prev; *(table)->t_entries.tqe_prev
= (table)->t_entries.tqe_next; ; ; } while (0)
;
360 free(table);
361 }
362
363 hostapd_log(HOSTAPD_LOG_VERBOSE1, "bye!");
364}
365
366int
367main(int argc, char *argv[])
368{
369 struct event ev_sigalrm;
370 struct event ev_sigterm;
371 struct event ev_sigquit;
372 struct event ev_sigint;
373 struct hostapd_config *cfg = &hostapd_cfg;
374 struct hostapd_iapp *iapp;
375 struct hostapd_apme *apme;
376 char *config = NULL((void *)0);
377 u_int debug = 0, ret;
378 int ch;
379
380 /* Set startup logging */
381 cfg->c_debug = 1;
382
383 /*
384 * Get and parse command line options
385 */
386 while ((ch = getopt(argc, argv, "f:D:dv")) != -1) {
387 switch (ch) {
388 case 'f':
389 config = optarg;
390 break;
391 case 'D':
392 if (hostapd_parse_symset(optarg) < 0)
393 hostapd_fatal("could not parse macro "
394 "definition %s\n", optarg);
395 break;
396 case 'd':
397 debug++;
398 break;
399 case 'v':
400 cfg->c_verbose++;
401 break;
402 default:
403 hostapd_usage();
404 }
405 }
406
407 argc -= optind;
408 argv += optind;
Value stored to 'argv' is never read
409 if (argc > 0)
410 hostapd_usage();
411
412 if (config == NULL((void *)0))
413 ret = strlcpy(cfg->c_config, HOSTAPD_CONFIG"/etc/hostapd.conf", sizeof(cfg->c_config));
414 else
415 ret = strlcpy(cfg->c_config, config, sizeof(cfg->c_config));
416 if (ret >= sizeof(cfg->c_config))
417 hostapd_fatal("invalid configuration file\n");
418
419 if (geteuid())
420 hostapd_fatal("need root privileges\n");
421
422 /* Parse the configuration file */
423 if (hostapd_parse_file(cfg) != 0)
424 hostapd_fatal("invalid configuration in %s\n", cfg->c_config);
425
426 iapp = &cfg->c_iapp;
427
428 if ((cfg->c_flags & HOSTAPD_CFG_F_IAPP0x02) == 0)
429 hostapd_fatal("IAPP interface not specified\n");
430
431 if (cfg->c_apme_dlt == 0)
432 cfg->c_apme_dlt = HOSTAPD_DLT105;
433
434 /*
435 * Setup the hostapd handlers
436 */
437 hostapd_udp_init(cfg);
438 hostapd_llc_init(cfg);
439
440 /*
441 * Set runtime logging and detach as daemon
442 */
443 if ((cfg->c_debug = debug) == 0) {
444 openlog(__progname, LOG_PID0x01 | LOG_NDELAY0x08, LOG_DAEMON(3<<3));
445 tzset();
446 if (daemon(0, 0) == -1)
447 hostapd_fatal("failed to daemonize\n");
448 }
449
450 if (cfg->c_flags & HOSTAPD_CFG_F_APME0x01) {
451 TAILQ_FOREACH(apme, &cfg->c_apmes, a_entries)for((apme) = ((&cfg->c_apmes)->tqh_first); (apme) !=
((void *)0); (apme) = ((apme)->a_entries.tqe_next))
452 hostapd_apme_init(apme);
453 } else
454 hostapd_log(HOSTAPD_LOG0, "%s: running without a Host AP",
455 iapp->i_iface);
456
457 /* Drop all privileges in an unprivileged child process */
458 hostapd_priv_init(cfg);
459
460 if (cfg->c_flags & HOSTAPD_CFG_F_APME0x01)
461 setproctitle("IAPP: %s, Host AP", iapp->i_iface);
462 else
463 setproctitle("IAPP: %s", iapp->i_iface);
464
465 /*
466 * Unprivileged child process
467 */
468
469 (void)event_init();
470
471 /*
472 * Set signal handlers
473 */
474 signal_set(&ev_sigalrm, SIGALRM, hostapd_sig_handler, NULL)event_set(&ev_sigalrm, 14, 0x08|0x10, hostapd_sig_handler
, ((void *)0))
;
475 signal_set(&ev_sigterm, SIGTERM, hostapd_sig_handler, NULL)event_set(&ev_sigterm, 15, 0x08|0x10, hostapd_sig_handler
, ((void *)0))
;
476 signal_set(&ev_sigquit, SIGQUIT, hostapd_sig_handler, NULL)event_set(&ev_sigquit, 3, 0x08|0x10, hostapd_sig_handler,
((void *)0))
;
477 signal_set(&ev_sigint, SIGINT, hostapd_sig_handler, NULL)event_set(&ev_sigint, 2, 0x08|0x10, hostapd_sig_handler, (
(void *)0))
;
478 signal_add(&ev_sigalrm, NULL)event_add(&ev_sigalrm, ((void *)0));
479 signal_add(&ev_sigterm, NULL)event_add(&ev_sigterm, ((void *)0));
480 signal_add(&ev_sigquit, NULL)event_add(&ev_sigquit, ((void *)0));
481 signal_add(&ev_sigint, NULL)event_add(&ev_sigint, ((void *)0));
482 signal(SIGHUP1, SIG_IGN(void (*)(int))1);
483 signal(SIGCHLD20, SIG_IGN(void (*)(int))1);
484
485 /* Initialize the IAPP protocol handler */
486 hostapd_iapp_init(cfg);
487
488 /*
489 * Schedule the Host AP listener
490 */
491 if (cfg->c_flags & HOSTAPD_CFG_F_APME0x01) {
492 TAILQ_FOREACH(apme, &cfg->c_apmes, a_entries)for((apme) = ((&cfg->c_apmes)->tqh_first); (apme) !=
((void *)0); (apme) = ((apme)->a_entries.tqe_next))
{
493 event_set(&apme->a_ev, apme->a_raw,
494 EV_READ0x02 | EV_PERSIST0x10, hostapd_apme_input, apme);
495 if (event_add(&apme->a_ev, NULL((void *)0)) == -1)
496 hostapd_fatal("failed to add APME event");
497 }
498 }
499
500 /*
501 * Schedule the IAPP listener
502 */
503 event_set(&iapp->i_udp_ev, iapp->i_udp, EV_READ0x02 | EV_PERSIST0x10,
504 hostapd_iapp_input, cfg);
505 if (event_add(&iapp->i_udp_ev, NULL((void *)0)) == -1)
506 hostapd_fatal("failed to add IAPP event");
507
508 hostapd_log(HOSTAPD_LOG0, "starting hostapd with pid %u",
509 getpid());
510
511 /* Run event loop */
512 if (event_dispatch() == -1)
513 hostapd_fatal("failed to dispatch hostapd");
514
515 /* Executed after the event loop has been terminated */
516 hostapd_cleanup(cfg);
517 return (EXIT_SUCCESS0);
518}
519
520void
521hostapd_randval(u_int8_t *buf, const u_int len)
522{
523 u_int32_t data = 0;
524 u_int i;
525
526 for (i = 0; i < len; i++) {
527 if ((i % sizeof(data)) == 0)
528 data = arc4random();
529 buf[i] = data & 0xff;
530 data >>= 8;
531 }
532}
533
534struct hostapd_table *
535hostapd_table_add(struct hostapd_config *cfg, const char *name)
536{
537 struct hostapd_table *table;
538
539 if (hostapd_table_lookup(cfg, name) != NULL((void *)0))
540 return (NULL((void *)0));
541 if ((table = (struct hostapd_table *)
542 calloc(1, sizeof(struct hostapd_table))) == NULL((void *)0))
543 return (NULL((void *)0));
544 if (strlcpy(table->t_name, name, sizeof(table->t_name)) >=
545 sizeof(table->t_name)) {
546 free(table);
547 return (NULL((void *)0));
548 }
549 RB_INIT(&table->t_tree)do { (&table->t_tree)->rbh_root = ((void *)0); } while
(0)
;
550 TAILQ_INIT(&table->t_mask_head)do { (&table->t_mask_head)->tqh_first = ((void *)0)
; (&table->t_mask_head)->tqh_last = &(&table
->t_mask_head)->tqh_first; } while (0)
;
551 TAILQ_INSERT_TAIL(&cfg->c_tables, table, t_entries)do { (table)->t_entries.tqe_next = ((void *)0); (table)->
t_entries.tqe_prev = (&cfg->c_tables)->tqh_last; *(
&cfg->c_tables)->tqh_last = (table); (&cfg->
c_tables)->tqh_last = &(table)->t_entries.tqe_next;
} while (0)
;
552
553 return (table);
554}
555
556struct hostapd_table *
557hostapd_table_lookup(struct hostapd_config *cfg, const char *name)
558{
559 struct hostapd_table *table;
560
561 TAILQ_FOREACH(table, &cfg->c_tables, t_entries)for((table) = ((&cfg->c_tables)->tqh_first); (table
) != ((void *)0); (table) = ((table)->t_entries.tqe_next))
{
562 if (strcmp(name, table->t_name) == 0)
563 return (table);
564 }
565
566 return (NULL((void *)0));
567}
568
569struct hostapd_entry *
570hostapd_entry_add(struct hostapd_table *table, u_int8_t *lladdr)
571{
572 struct hostapd_entry *entry;
573
574 if (hostapd_entry_lookup(table, lladdr) != NULL((void *)0))
575 return (NULL((void *)0));
576
577 if ((entry = (struct hostapd_entry *)
578 calloc(1, sizeof(struct hostapd_entry))) == NULL((void *)0))
579 return (NULL((void *)0));
580
581 bcopy(lladdr, entry->e_lladdr, IEEE80211_ADDR_LEN6);
582 RB_INSERT(hostapd_tree, &table->t_tree, entry)hostapd_tree_RB_INSERT(&table->t_tree, entry);
583
584 return (entry);
585}
586
587struct hostapd_entry *
588hostapd_entry_lookup(struct hostapd_table *table, u_int8_t *lladdr)
589{
590 struct hostapd_entry *entry, key;
591
592 bcopy(lladdr, key.e_lladdr, IEEE80211_ADDR_LEN6);
593 if ((entry = RB_FIND(hostapd_tree, &table->t_tree, &key)hostapd_tree_RB_FIND(&table->t_tree, &key)) != NULL((void *)0))
594 return (entry);
595
596 /* Masked entries can't be handled by the red-black tree */
597 TAILQ_FOREACH(entry, &table->t_mask_head, e_entries)for((entry) = ((&table->t_mask_head)->tqh_first); (
entry) != ((void *)0); (entry) = ((entry)->e_entries.tqe_next
))
{
598 if (HOSTAPD_ENTRY_MASK_MATCH(entry, lladdr)( ((entry)->e_lladdr[0] == ((lladdr)[0] & (entry)->
e_addr.a_mask[0])) && ((entry)->e_lladdr[1] == ((lladdr
)[1] & (entry)->e_addr.a_mask[1])) && ((entry)
->e_lladdr[2] == ((lladdr)[2] & (entry)->e_addr.a_mask
[2])) && ((entry)->e_lladdr[3] == ((lladdr)[3] &
(entry)->e_addr.a_mask[3])) && ((entry)->e_lladdr
[4] == ((lladdr)[4] & (entry)->e_addr.a_mask[4])) &&
((entry)->e_lladdr[5] == ((lladdr)[5] & (entry)->e_addr
.a_mask[5])) )
)
599 return (entry);
600 }
601
602 return (NULL((void *)0));
603}
604
605void
606hostapd_entry_update(struct hostapd_table *table, struct hostapd_entry *entry)
607{
608 RB_REMOVE(hostapd_tree, &table->t_tree, entry)hostapd_tree_RB_REMOVE(&table->t_tree, entry);
609
610 /* Apply mask to entry */
611 if (entry->e_flags & HOSTAPD_ENTRY_F_MASK0x01) {
612 HOSTAPD_ENTRY_MASK_ADD(entry->e_lladdr, entry->e_mask)do { (entry->e_lladdr)[0] &= (entry->e_addr.a_mask)
[0]; (entry->e_lladdr)[1] &= (entry->e_addr.a_mask)
[1]; (entry->e_lladdr)[2] &= (entry->e_addr.a_mask)
[2]; (entry->e_lladdr)[3] &= (entry->e_addr.a_mask)
[3]; (entry->e_lladdr)[4] &= (entry->e_addr.a_mask)
[4]; (entry->e_lladdr)[5] &= (entry->e_addr.a_mask)
[5]; } while (0);
;
613 TAILQ_INSERT_TAIL(&table->t_mask_head, entry, e_entries)do { (entry)->e_entries.tqe_next = ((void *)0); (entry)->
e_entries.tqe_prev = (&table->t_mask_head)->tqh_last
; *(&table->t_mask_head)->tqh_last = (entry); (&
table->t_mask_head)->tqh_last = &(entry)->e_entries
.tqe_next; } while (0)
;
614 } else {
615 RB_INSERT(hostapd_tree, &table->t_tree, entry)hostapd_tree_RB_INSERT(&table->t_tree, entry);
616 }
617}
618
619static __inline int
620hostapd_entry_cmp(struct hostapd_entry *a, struct hostapd_entry *b)
621{
622 return (memcmp(a->e_lladdr, b->e_lladdr, IEEE80211_ADDR_LEN6));
623}
624
625RB_GENERATE(hostapd_tree, hostapd_entry, e_nodes, hostapd_entry_cmp)void hostapd_tree_RB_INSERT_COLOR(struct hostapd_tree *head, struct
hostapd_entry *elm) { struct hostapd_entry *parent, *gparent
, *tmp; while ((parent = (elm)->e_nodes.rbe_parent) &&
(parent)->e_nodes.rbe_color == 1) { gparent = (parent)->
e_nodes.rbe_parent; if (parent == (gparent)->e_nodes.rbe_left
) { tmp = (gparent)->e_nodes.rbe_right; if (tmp &&
(tmp)->e_nodes.rbe_color == 1) { (tmp)->e_nodes.rbe_color
= 0; do { (parent)->e_nodes.rbe_color = 0; (gparent)->
e_nodes.rbe_color = 1; } while (0); elm = gparent; continue; }
if ((parent)->e_nodes.rbe_right == elm) { do { (tmp) = (parent
)->e_nodes.rbe_right; if (((parent)->e_nodes.rbe_right =
(tmp)->e_nodes.rbe_left)) { ((tmp)->e_nodes.rbe_left)->
e_nodes.rbe_parent = (parent); } do {} while (0); if (((tmp)->
e_nodes.rbe_parent = (parent)->e_nodes.rbe_parent)) { if (
(parent) == ((parent)->e_nodes.rbe_parent)->e_nodes.rbe_left
) ((parent)->e_nodes.rbe_parent)->e_nodes.rbe_left = (tmp
); else ((parent)->e_nodes.rbe_parent)->e_nodes.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->e_nodes
.rbe_left = (parent); (parent)->e_nodes.rbe_parent = (tmp)
; do {} while (0); if (((tmp)->e_nodes.rbe_parent)) do {} while
(0); } while (0); tmp = parent; parent = elm; elm = tmp; } do
{ (parent)->e_nodes.rbe_color = 0; (gparent)->e_nodes.
rbe_color = 1; } while (0); do { (tmp) = (gparent)->e_nodes
.rbe_left; if (((gparent)->e_nodes.rbe_left = (tmp)->e_nodes
.rbe_right)) { ((tmp)->e_nodes.rbe_right)->e_nodes.rbe_parent
= (gparent); } do {} while (0); if (((tmp)->e_nodes.rbe_parent
= (gparent)->e_nodes.rbe_parent)) { if ((gparent) == ((gparent
)->e_nodes.rbe_parent)->e_nodes.rbe_left) ((gparent)->
e_nodes.rbe_parent)->e_nodes.rbe_left = (tmp); else ((gparent
)->e_nodes.rbe_parent)->e_nodes.rbe_right = (tmp); } else
(head)->rbh_root = (tmp); (tmp)->e_nodes.rbe_right = (
gparent); (gparent)->e_nodes.rbe_parent = (tmp); do {} while
(0); if (((tmp)->e_nodes.rbe_parent)) do {} while (0); } while
(0); } else { tmp = (gparent)->e_nodes.rbe_left; if (tmp &&
(tmp)->e_nodes.rbe_color == 1) { (tmp)->e_nodes.rbe_color
= 0; do { (parent)->e_nodes.rbe_color = 0; (gparent)->
e_nodes.rbe_color = 1; } while (0); elm = gparent; continue; }
if ((parent)->e_nodes.rbe_left == elm) { do { (tmp) = (parent
)->e_nodes.rbe_left; if (((parent)->e_nodes.rbe_left = (
tmp)->e_nodes.rbe_right)) { ((tmp)->e_nodes.rbe_right)->
e_nodes.rbe_parent = (parent); } do {} while (0); if (((tmp)->
e_nodes.rbe_parent = (parent)->e_nodes.rbe_parent)) { if (
(parent) == ((parent)->e_nodes.rbe_parent)->e_nodes.rbe_left
) ((parent)->e_nodes.rbe_parent)->e_nodes.rbe_left = (tmp
); else ((parent)->e_nodes.rbe_parent)->e_nodes.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->e_nodes
.rbe_right = (parent); (parent)->e_nodes.rbe_parent = (tmp
); do {} while (0); if (((tmp)->e_nodes.rbe_parent)) do {}
while (0); } while (0); tmp = parent; parent = elm; elm = tmp
; } do { (parent)->e_nodes.rbe_color = 0; (gparent)->e_nodes
.rbe_color = 1; } while (0); do { (tmp) = (gparent)->e_nodes
.rbe_right; if (((gparent)->e_nodes.rbe_right = (tmp)->
e_nodes.rbe_left)) { ((tmp)->e_nodes.rbe_left)->e_nodes
.rbe_parent = (gparent); } do {} while (0); if (((tmp)->e_nodes
.rbe_parent = (gparent)->e_nodes.rbe_parent)) { if ((gparent
) == ((gparent)->e_nodes.rbe_parent)->e_nodes.rbe_left)
((gparent)->e_nodes.rbe_parent)->e_nodes.rbe_left = (tmp
); else ((gparent)->e_nodes.rbe_parent)->e_nodes.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->e_nodes
.rbe_left = (gparent); (gparent)->e_nodes.rbe_parent = (tmp
); do {} while (0); if (((tmp)->e_nodes.rbe_parent)) do {}
while (0); } while (0); } } (head->rbh_root)->e_nodes.
rbe_color = 0; } void hostapd_tree_RB_REMOVE_COLOR(struct hostapd_tree
*head, struct hostapd_entry *parent, struct hostapd_entry *elm
) { struct hostapd_entry *tmp; while ((elm == ((void *)0) || (
elm)->e_nodes.rbe_color == 0) && elm != (head)->
rbh_root) { if ((parent)->e_nodes.rbe_left == elm) { tmp =
(parent)->e_nodes.rbe_right; if ((tmp)->e_nodes.rbe_color
== 1) { do { (tmp)->e_nodes.rbe_color = 0; (parent)->e_nodes
.rbe_color = 1; } while (0); do { (tmp) = (parent)->e_nodes
.rbe_right; if (((parent)->e_nodes.rbe_right = (tmp)->e_nodes
.rbe_left)) { ((tmp)->e_nodes.rbe_left)->e_nodes.rbe_parent
= (parent); } do {} while (0); if (((tmp)->e_nodes.rbe_parent
= (parent)->e_nodes.rbe_parent)) { if ((parent) == ((parent
)->e_nodes.rbe_parent)->e_nodes.rbe_left) ((parent)->
e_nodes.rbe_parent)->e_nodes.rbe_left = (tmp); else ((parent
)->e_nodes.rbe_parent)->e_nodes.rbe_right = (tmp); } else
(head)->rbh_root = (tmp); (tmp)->e_nodes.rbe_left = (parent
); (parent)->e_nodes.rbe_parent = (tmp); do {} while (0); if
(((tmp)->e_nodes.rbe_parent)) do {} while (0); } while (0
); tmp = (parent)->e_nodes.rbe_right; } if (((tmp)->e_nodes
.rbe_left == ((void *)0) || ((tmp)->e_nodes.rbe_left)->
e_nodes.rbe_color == 0) && ((tmp)->e_nodes.rbe_right
== ((void *)0) || ((tmp)->e_nodes.rbe_right)->e_nodes.
rbe_color == 0)) { (tmp)->e_nodes.rbe_color = 1; elm = parent
; parent = (elm)->e_nodes.rbe_parent; } else { if ((tmp)->
e_nodes.rbe_right == ((void *)0) || ((tmp)->e_nodes.rbe_right
)->e_nodes.rbe_color == 0) { struct hostapd_entry *oleft; if
((oleft = (tmp)->e_nodes.rbe_left)) (oleft)->e_nodes.rbe_color
= 0; (tmp)->e_nodes.rbe_color = 1; do { (oleft) = (tmp)->
e_nodes.rbe_left; if (((tmp)->e_nodes.rbe_left = (oleft)->
e_nodes.rbe_right)) { ((oleft)->e_nodes.rbe_right)->e_nodes
.rbe_parent = (tmp); } do {} while (0); if (((oleft)->e_nodes
.rbe_parent = (tmp)->e_nodes.rbe_parent)) { if ((tmp) == (
(tmp)->e_nodes.rbe_parent)->e_nodes.rbe_left) ((tmp)->
e_nodes.rbe_parent)->e_nodes.rbe_left = (oleft); else ((tmp
)->e_nodes.rbe_parent)->e_nodes.rbe_right = (oleft); } else
(head)->rbh_root = (oleft); (oleft)->e_nodes.rbe_right
= (tmp); (tmp)->e_nodes.rbe_parent = (oleft); do {} while
(0); if (((oleft)->e_nodes.rbe_parent)) do {} while (0); }
while (0); tmp = (parent)->e_nodes.rbe_right; } (tmp)->
e_nodes.rbe_color = (parent)->e_nodes.rbe_color; (parent)->
e_nodes.rbe_color = 0; if ((tmp)->e_nodes.rbe_right) ((tmp
)->e_nodes.rbe_right)->e_nodes.rbe_color = 0; do { (tmp
) = (parent)->e_nodes.rbe_right; if (((parent)->e_nodes
.rbe_right = (tmp)->e_nodes.rbe_left)) { ((tmp)->e_nodes
.rbe_left)->e_nodes.rbe_parent = (parent); } do {} while (
0); if (((tmp)->e_nodes.rbe_parent = (parent)->e_nodes.
rbe_parent)) { if ((parent) == ((parent)->e_nodes.rbe_parent
)->e_nodes.rbe_left) ((parent)->e_nodes.rbe_parent)->
e_nodes.rbe_left = (tmp); else ((parent)->e_nodes.rbe_parent
)->e_nodes.rbe_right = (tmp); } else (head)->rbh_root =
(tmp); (tmp)->e_nodes.rbe_left = (parent); (parent)->e_nodes
.rbe_parent = (tmp); do {} while (0); if (((tmp)->e_nodes.
rbe_parent)) do {} while (0); } while (0); elm = (head)->rbh_root
; break; } } else { tmp = (parent)->e_nodes.rbe_left; if (
(tmp)->e_nodes.rbe_color == 1) { do { (tmp)->e_nodes.rbe_color
= 0; (parent)->e_nodes.rbe_color = 1; } while (0); do { (
tmp) = (parent)->e_nodes.rbe_left; if (((parent)->e_nodes
.rbe_left = (tmp)->e_nodes.rbe_right)) { ((tmp)->e_nodes
.rbe_right)->e_nodes.rbe_parent = (parent); } do {} while (
0); if (((tmp)->e_nodes.rbe_parent = (parent)->e_nodes.
rbe_parent)) { if ((parent) == ((parent)->e_nodes.rbe_parent
)->e_nodes.rbe_left) ((parent)->e_nodes.rbe_parent)->
e_nodes.rbe_left = (tmp); else ((parent)->e_nodes.rbe_parent
)->e_nodes.rbe_right = (tmp); } else (head)->rbh_root =
(tmp); (tmp)->e_nodes.rbe_right = (parent); (parent)->
e_nodes.rbe_parent = (tmp); do {} while (0); if (((tmp)->e_nodes
.rbe_parent)) do {} while (0); } while (0); tmp = (parent)->
e_nodes.rbe_left; } if (((tmp)->e_nodes.rbe_left == ((void
*)0) || ((tmp)->e_nodes.rbe_left)->e_nodes.rbe_color ==
0) && ((tmp)->e_nodes.rbe_right == ((void *)0) ||
((tmp)->e_nodes.rbe_right)->e_nodes.rbe_color == 0)) {
(tmp)->e_nodes.rbe_color = 1; elm = parent; parent = (elm
)->e_nodes.rbe_parent; } else { if ((tmp)->e_nodes.rbe_left
== ((void *)0) || ((tmp)->e_nodes.rbe_left)->e_nodes.rbe_color
== 0) { struct hostapd_entry *oright; if ((oright = (tmp)->
e_nodes.rbe_right)) (oright)->e_nodes.rbe_color = 0; (tmp)
->e_nodes.rbe_color = 1; do { (oright) = (tmp)->e_nodes
.rbe_right; if (((tmp)->e_nodes.rbe_right = (oright)->e_nodes
.rbe_left)) { ((oright)->e_nodes.rbe_left)->e_nodes.rbe_parent
= (tmp); } do {} while (0); if (((oright)->e_nodes.rbe_parent
= (tmp)->e_nodes.rbe_parent)) { if ((tmp) == ((tmp)->e_nodes
.rbe_parent)->e_nodes.rbe_left) ((tmp)->e_nodes.rbe_parent
)->e_nodes.rbe_left = (oright); else ((tmp)->e_nodes.rbe_parent
)->e_nodes.rbe_right = (oright); } else (head)->rbh_root
= (oright); (oright)->e_nodes.rbe_left = (tmp); (tmp)->
e_nodes.rbe_parent = (oright); do {} while (0); if (((oright)
->e_nodes.rbe_parent)) do {} while (0); } while (0); tmp =
(parent)->e_nodes.rbe_left; } (tmp)->e_nodes.rbe_color
= (parent)->e_nodes.rbe_color; (parent)->e_nodes.rbe_color
= 0; if ((tmp)->e_nodes.rbe_left) ((tmp)->e_nodes.rbe_left
)->e_nodes.rbe_color = 0; do { (tmp) = (parent)->e_nodes
.rbe_left; if (((parent)->e_nodes.rbe_left = (tmp)->e_nodes
.rbe_right)) { ((tmp)->e_nodes.rbe_right)->e_nodes.rbe_parent
= (parent); } do {} while (0); if (((tmp)->e_nodes.rbe_parent
= (parent)->e_nodes.rbe_parent)) { if ((parent) == ((parent
)->e_nodes.rbe_parent)->e_nodes.rbe_left) ((parent)->
e_nodes.rbe_parent)->e_nodes.rbe_left = (tmp); else ((parent
)->e_nodes.rbe_parent)->e_nodes.rbe_right = (tmp); } else
(head)->rbh_root = (tmp); (tmp)->e_nodes.rbe_right = (
parent); (parent)->e_nodes.rbe_parent = (tmp); do {} while
(0); if (((tmp)->e_nodes.rbe_parent)) do {} while (0); } while
(0); elm = (head)->rbh_root; break; } } } if (elm) (elm)->
e_nodes.rbe_color = 0; } struct hostapd_entry * hostapd_tree_RB_REMOVE
(struct hostapd_tree *head, struct hostapd_entry *elm) { struct
hostapd_entry *child, *parent, *old = elm; int color; if ((elm
)->e_nodes.rbe_left == ((void *)0)) child = (elm)->e_nodes
.rbe_right; else if ((elm)->e_nodes.rbe_right == ((void *)
0)) child = (elm)->e_nodes.rbe_left; else { struct hostapd_entry
*left; elm = (elm)->e_nodes.rbe_right; while ((left = (elm
)->e_nodes.rbe_left)) elm = left; child = (elm)->e_nodes
.rbe_right; parent = (elm)->e_nodes.rbe_parent; color = (elm
)->e_nodes.rbe_color; if (child) (child)->e_nodes.rbe_parent
= parent; if (parent) { if ((parent)->e_nodes.rbe_left ==
elm) (parent)->e_nodes.rbe_left = child; else (parent)->
e_nodes.rbe_right = child; do {} while (0); } else (head)->
rbh_root = child; if ((elm)->e_nodes.rbe_parent == old) parent
= elm; (elm)->e_nodes = (old)->e_nodes; if ((old)->
e_nodes.rbe_parent) { if (((old)->e_nodes.rbe_parent)->
e_nodes.rbe_left == old) ((old)->e_nodes.rbe_parent)->e_nodes
.rbe_left = elm; else ((old)->e_nodes.rbe_parent)->e_nodes
.rbe_right = elm; do {} while (0); } else (head)->rbh_root
= elm; ((old)->e_nodes.rbe_left)->e_nodes.rbe_parent =
elm; if ((old)->e_nodes.rbe_right) ((old)->e_nodes.rbe_right
)->e_nodes.rbe_parent = elm; if (parent) { left = parent; do
{ do {} while (0); } while ((left = (left)->e_nodes.rbe_parent
)); } goto color; } parent = (elm)->e_nodes.rbe_parent; color
= (elm)->e_nodes.rbe_color; if (child) (child)->e_nodes
.rbe_parent = parent; if (parent) { if ((parent)->e_nodes.
rbe_left == elm) (parent)->e_nodes.rbe_left = child; else (
parent)->e_nodes.rbe_right = child; do {} while (0); } else
(head)->rbh_root = child; color: if (color == 0) hostapd_tree_RB_REMOVE_COLOR
(head, parent, child); return (old); } struct hostapd_entry *
hostapd_tree_RB_INSERT(struct hostapd_tree *head, struct hostapd_entry
*elm) { struct hostapd_entry *tmp; struct hostapd_entry *parent
= ((void *)0); int comp = 0; tmp = (head)->rbh_root; while
(tmp) { parent = tmp; comp = (hostapd_entry_cmp)(elm, parent
); if (comp < 0) tmp = (tmp)->e_nodes.rbe_left; else if
(comp > 0) tmp = (tmp)->e_nodes.rbe_right; else return
(tmp); } do { (elm)->e_nodes.rbe_parent = parent; (elm)->
e_nodes.rbe_left = (elm)->e_nodes.rbe_right = ((void *)0);
(elm)->e_nodes.rbe_color = 1; } while (0); if (parent != (
(void *)0)) { if (comp < 0) (parent)->e_nodes.rbe_left =
elm; else (parent)->e_nodes.rbe_right = elm; do {} while (
0); } else (head)->rbh_root = elm; hostapd_tree_RB_INSERT_COLOR
(head, elm); return (((void *)0)); } struct hostapd_entry * hostapd_tree_RB_FIND
(struct hostapd_tree *head, struct hostapd_entry *elm) { struct
hostapd_entry *tmp = (head)->rbh_root; int comp; while (tmp
) { comp = hostapd_entry_cmp(elm, tmp); if (comp < 0) tmp =
(tmp)->e_nodes.rbe_left; else if (comp > 0) tmp = (tmp
)->e_nodes.rbe_right; else return (tmp); } return (((void *
)0)); } struct hostapd_entry * hostapd_tree_RB_NFIND(struct hostapd_tree
*head, struct hostapd_entry *elm) { struct hostapd_entry *tmp
= (head)->rbh_root; struct hostapd_entry *res = ((void *)
0); int comp; while (tmp) { comp = hostapd_entry_cmp(elm, tmp
); if (comp < 0) { res = tmp; tmp = (tmp)->e_nodes.rbe_left
; } else if (comp > 0) tmp = (tmp)->e_nodes.rbe_right; else
return (tmp); } return (res); } struct hostapd_entry * hostapd_tree_RB_NEXT
(struct hostapd_entry *elm) { if ((elm)->e_nodes.rbe_right
) { elm = (elm)->e_nodes.rbe_right; while ((elm)->e_nodes
.rbe_left) elm = (elm)->e_nodes.rbe_left; } else { if ((elm
)->e_nodes.rbe_parent && (elm == ((elm)->e_nodes
.rbe_parent)->e_nodes.rbe_left)) elm = (elm)->e_nodes.rbe_parent
; else { while ((elm)->e_nodes.rbe_parent && (elm ==
((elm)->e_nodes.rbe_parent)->e_nodes.rbe_right)) elm =
(elm)->e_nodes.rbe_parent; elm = (elm)->e_nodes.rbe_parent
; } } return (elm); } struct hostapd_entry * hostapd_tree_RB_PREV
(struct hostapd_entry *elm) { if ((elm)->e_nodes.rbe_left)
{ elm = (elm)->e_nodes.rbe_left; while ((elm)->e_nodes
.rbe_right) elm = (elm)->e_nodes.rbe_right; } else { if ((
elm)->e_nodes.rbe_parent && (elm == ((elm)->e_nodes
.rbe_parent)->e_nodes.rbe_right)) elm = (elm)->e_nodes.
rbe_parent; else { while ((elm)->e_nodes.rbe_parent &&
(elm == ((elm)->e_nodes.rbe_parent)->e_nodes.rbe_left)
) elm = (elm)->e_nodes.rbe_parent; elm = (elm)->e_nodes
.rbe_parent; } } return (elm); } struct hostapd_entry * hostapd_tree_RB_MINMAX
(struct hostapd_tree *head, int val) { struct hostapd_entry *
tmp = (head)->rbh_root; struct hostapd_entry *parent = ((void
*)0); while (tmp) { parent = tmp; if (val < 0) tmp = (tmp
)->e_nodes.rbe_left; else tmp = (tmp)->e_nodes.rbe_right
; } return (parent); }
;