mirror of https://github.com/sonertari/SSLproxy
Update with sslsplit develop changes, especially content logging
Change SIGHUP to behave like SIGUSR1pull/13/head
parent
12ecc96648
commit
52d37297b6
@ -1,8 +1,151 @@
|
||||
language: c
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
script: make && make travis && ./sslproxy -V
|
||||
before_install:
|
||||
- sudo apt-get update -qq
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: SSL=ubuntu EVENT=ubuntu
|
||||
before_install:
|
||||
- sudo apt-get install -qq libssl-dev libevent-dev libnet1-dev libpcap-dev check
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env: SSL=ubuntu EVENT=ubuntu
|
||||
before_install:
|
||||
- sudo apt-get install -qq libssl-dev libevent-dev libnet1-dev libpcap-dev check
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env: FEATURES=-DWITHOUT_MIRROR SSL=ubuntu EVENT=ubuntu
|
||||
before_install:
|
||||
- sudo apt-get install -qq libssl-dev libevent-dev check
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env: SSL=openssl-0.9.8zh EVENT=libevent-2.0.22
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/opt
|
||||
before_install:
|
||||
- sudo apt-get install -qq libnet1-dev libpcap-dev check
|
||||
install:
|
||||
- ./Mk/bin/install-opt.sh
|
||||
before_script:
|
||||
- export OPENSSL_BASE="$HOME/opt/$SSL"
|
||||
- export LIBEVENT_BASE="$HOME/opt/$EVENT"
|
||||
- export LD_LIBRARY_PATH="$HOME/opt/$SSL/lib":"$HOME/opt/$EVENT/lib"
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env: SSL=openssl-1.0.0s EVENT=libevent-2.0.22
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/opt
|
||||
before_install:
|
||||
- sudo apt-get install -qq libnet1-dev libpcap-dev check
|
||||
install:
|
||||
- ./Mk/bin/install-opt.sh
|
||||
before_script:
|
||||
- export OPENSSL_BASE="$HOME/opt/$SSL"
|
||||
- export LIBEVENT_BASE="$HOME/opt/$EVENT"
|
||||
- export LD_LIBRARY_PATH="$HOME/opt/$SSL/lib":"$HOME/opt/$EVENT/lib"
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env: SSL=openssl-1.0.1u EVENT=libevent-2.0.22
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/opt
|
||||
before_install:
|
||||
- sudo apt-get install -qq libnet1-dev libpcap-dev check
|
||||
install:
|
||||
- ./Mk/bin/install-opt.sh
|
||||
before_script:
|
||||
- export OPENSSL_BASE="$HOME/opt/$SSL"
|
||||
- export LIBEVENT_BASE="$HOME/opt/$EVENT"
|
||||
- export LD_LIBRARY_PATH="$HOME/opt/$SSL/lib":"$HOME/opt/$EVENT/lib"
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env: SSL=openssl-1.0.2p EVENT=libevent-2.0.22
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/opt
|
||||
before_install:
|
||||
- sudo apt-get install -qq libnet1-dev libpcap-dev check
|
||||
install:
|
||||
- ./Mk/bin/install-opt.sh
|
||||
before_script:
|
||||
- export OPENSSL_BASE="$HOME/opt/$SSL"
|
||||
- export LIBEVENT_BASE="$HOME/opt/$EVENT"
|
||||
- export LD_LIBRARY_PATH="$HOME/opt/$SSL/lib":"$HOME/opt/$EVENT/lib"
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env: SSL=openssl-1.1.0i EVENT=libevent-2.1.8
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/opt
|
||||
before_install:
|
||||
- sudo apt-get install -qq libnet1-dev libpcap-dev check
|
||||
install:
|
||||
- ./Mk/bin/install-opt.sh
|
||||
before_script:
|
||||
- export OPENSSL_BASE="$HOME/opt/$SSL"
|
||||
- export LIBEVENT_BASE="$HOME/opt/$EVENT"
|
||||
- export LD_LIBRARY_PATH="$HOME/opt/$SSL/lib":"$HOME/opt/$EVENT/lib"
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env: SSL=openssl-1.1.1 EVENT=libevent-2.1.8
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/opt
|
||||
before_install:
|
||||
- sudo apt-get install -qq libnet1-dev libpcap-dev check
|
||||
install:
|
||||
- ./Mk/bin/install-opt.sh
|
||||
before_script:
|
||||
- export OPENSSL_BASE="$HOME/opt/$SSL"
|
||||
- export LIBEVENT_BASE="$HOME/opt/$EVENT"
|
||||
- export LD_LIBRARY_PATH="$HOME/opt/$SSL/lib":"$HOME/opt/$EVENT/lib"
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env: SSL=libressl-2.2.7 EVENT=libevent-2.0.22
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/opt
|
||||
before_install:
|
||||
- sudo apt-get install -qq libnet1-dev libpcap-dev check
|
||||
install:
|
||||
- ./Mk/bin/install-opt.sh
|
||||
before_script:
|
||||
- export OPENSSL_BASE="$HOME/opt/$SSL"
|
||||
- export LIBEVENT_BASE="$HOME/opt/$EVENT"
|
||||
- export LD_LIBRARY_PATH="$HOME/opt/$SSL/lib":"$HOME/opt/$EVENT/lib"
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env: SSL=libressl-2.7.4 EVENT=libevent-2.1.8
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/opt
|
||||
before_install:
|
||||
- sudo apt-get install -qq libnet1-dev libpcap-dev check
|
||||
install:
|
||||
- ./Mk/bin/install-opt.sh
|
||||
before_script:
|
||||
- export OPENSSL_BASE="$HOME/opt/$SSL"
|
||||
- export LIBEVENT_BASE="$HOME/opt/$EVENT"
|
||||
- export LD_LIBRARY_PATH="$HOME/opt/$SSL/lib":"$HOME/opt/$EVENT/lib"
|
||||
- os: osx
|
||||
env: SSL=homebrew EVENT=homebrew
|
||||
cache:
|
||||
directories:
|
||||
- /usr/local/Cellar/openssl
|
||||
- /usr/local/opt/openssl
|
||||
- /usr/local/Cellar/libevent
|
||||
- /usr/local/opt/libevent
|
||||
- /usr/local/Cellar/libnet
|
||||
- /usr/local/opt/libnet
|
||||
- /usr/local/Cellar/libpcap
|
||||
- /usr/local/opt/libpcap
|
||||
- /usr/local/Cellar/check
|
||||
- /usr/local/opt/check
|
||||
before_install:
|
||||
- test -d /usr/local/opt/openssl/lib || { rmdir /usr/local/opt/openssl; brew install openssl; }
|
||||
- test -d /usr/local/opt/libevent/lib || { rmdir /usr/local/opt/libevent; brew install libevent; }
|
||||
- test -d /usr/local/opt/libnet/lib || { rmdir /usr/local/opt/libnet; brew install libnet; }
|
||||
- test -d /usr/local/opt/libpcap/lib || { rmdir /usr/local/opt/libpcap; brew install libpcap; }
|
||||
- test -d /usr/local/opt/check/lib || { rmdir /usr/local/opt/check; brew install check; }
|
||||
|
@ -0,0 +1,42 @@
|
||||
# macOS Xcode and SDK selection makefile
|
||||
# Authored 2018, Daniel Roethlisberger
|
||||
# Provided under the Unlicense
|
||||
# https://github.com/droe/example.kext
|
||||
|
||||
# DEVELOPER_DIR override Xcode Command Line Developer Tools directory
|
||||
# MACOSX_VERSION_MIN minimal version of macOS to target, e.g. 10.11
|
||||
# SDK SDK name to build against (e.g. macosx, macosx10.11, ...);
|
||||
# for kernel extensions, use macosx$(MACOSX_VERSION_MIN)
|
||||
|
||||
# target specific macOS min version
|
||||
ifdef MACOSX_VERSION_MIN
|
||||
CFLAGS+= -mmacosx-version-min=$(MACOSX_VERSION_MIN)
|
||||
LDFLAGS+= -mmacosx-version-min=$(MACOSX_VERSION_MIN)
|
||||
endif
|
||||
|
||||
# select specific Xcode
|
||||
ifdef DEVELOPER_DIR
|
||||
ifndef SDK
|
||||
SDK:= macosx
|
||||
endif
|
||||
else
|
||||
DEVELOPER_DIR:= $(shell xcode-select -p)
|
||||
endif
|
||||
|
||||
# activate the selected Xcode and SDK
|
||||
ifdef SDK
|
||||
SDKPATH:= $(shell DEVELOPER_DIR="$(DEVELOPER_DIR)" xcrun -find -sdk $(SDK) --show-sdk-path||echo none)
|
||||
ifeq "$(SDKPATH)" "none"
|
||||
$(error SDK not found)
|
||||
endif
|
||||
CPPFLAGS+= -isysroot $(SDKPATH)
|
||||
LDFLAGS+= -isysroot $(SDKPATH)
|
||||
CC:= $(shell DEVELOPER_DIR="$(DEVELOPER_DIR)" xcrun -find -sdk $(SDK) cc||echo false)
|
||||
CXX:= $(shell DEVELOPER_DIR="$(DEVELOPER_DIR)" xcrun -find -sdk $(SDK) c++||echo false)
|
||||
CODESIGN:= $(shell DEVELOPER_DIR="$(DEVELOPER_DIR)" xcrun -find -sdk $(SDK) codesign||echo false)
|
||||
else
|
||||
CC?= cc
|
||||
CXX?= c++
|
||||
CODESIGN?= codesign
|
||||
endif
|
||||
|
@ -0,0 +1,17 @@
|
||||
FROM alpine:3.8 as builder
|
||||
RUN apk add --no-cache fts libressl libevent libpcap libnet
|
||||
RUN apk add --no-cache libressl-dev libevent-dev libpcap-dev libnet-dev check-dev libc-dev fts-dev linux-headers gcc make git
|
||||
COPY . /opt/sslproxy
|
||||
WORKDIR /opt/sslproxy
|
||||
ENV LIBS -lfts
|
||||
ENV TCPPFLAGS -DDOCKER
|
||||
RUN export SOURCE_DATE_EPOCH=$(stat -c '%Y' *.c *.h|sort -r|head -1); make clean && make all test
|
||||
|
||||
FROM alpine:3.8 as production
|
||||
RUN apk add --no-cache fts libressl libevent libpcap libnet
|
||||
WORKDIR /root/
|
||||
COPY --from=builder /opt/sslproxy/sslproxy /usr/local/bin/sslproxy
|
||||
#EXPOSE 80 443
|
||||
ENTRYPOINT [ "sslproxy" ]
|
||||
CMD [ "-V" ]
|
||||
|
@ -0,0 +1,66 @@
|
||||
/*-
|
||||
* SSLsplit - transparent SSL/TLS interception
|
||||
* https://www.roe.ch/SSLsplit
|
||||
*
|
||||
* Copyright (c) 2009-2018, Daniel Roethlisberger <daniel@roe.ch>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "logbuf.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <check.h>
|
||||
|
||||
START_TEST(logbuf_make_contiguous_01)
|
||||
{
|
||||
logbuf_t *lb;
|
||||
|
||||
lb = logbuf_new_printf(NULL, "%s", "789");
|
||||
lb = logbuf_new_printf(lb, "%s", "456");
|
||||
lb = logbuf_new_printf(lb, "%s", "123");
|
||||
lb = logbuf_make_contiguous(lb);
|
||||
fail_unless(!!lb, "logbuf_make_contiguous failed");
|
||||
fail_unless(!lb->next, "multiple buffers");
|
||||
fail_unless(logbuf_size(lb) == 9, "buffer size incorrect");
|
||||
fail_unless(!memcmp(lb->buf, "123456789", 9), "buffer value incorrect");
|
||||
logbuf_free(lb);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite *
|
||||
logbuf_suite(void)
|
||||
{
|
||||
Suite *s;
|
||||
TCase *tc;
|
||||
|
||||
s = suite_create("logbuf");
|
||||
|
||||
tc = tcase_create("");
|
||||
tcase_add_test(tc, logbuf_make_contiguous_01);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/* vim: set noet ft=c: */
|
@ -0,0 +1,843 @@
|
||||
/*-
|
||||
* SSLsplit - transparent SSL/TLS interception
|
||||
* https://www.roe.ch/SSLsplit
|
||||
*
|
||||
* Copyright (c) 2009-2018, Daniel Roethlisberger <daniel@roe.ch>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "logpkt.h"
|
||||
|
||||
#include "sys.h"
|
||||
#include "log.h"
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef WITHOUT_MIRROR
|
||||
#include <pcap.h>
|
||||
#endif /* !WITHOUT_MIRROR */
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t magic_number; /* magic number */
|
||||
uint16_t version_major; /* major version number */
|
||||
uint16_t version_minor; /* minor version number */
|
||||
uint32_t thiszone; /* GMT to local correction */
|
||||
uint32_t sigfigs; /* accuracy of timestamps */
|
||||
uint32_t snaplen; /* max length of captured packets, in octets */
|
||||
uint32_t network; /* data link type */
|
||||
} pcap_file_hdr_t;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t ts_sec; /* timestamp seconds */
|
||||
uint32_t ts_usec; /* timestamp microseconds */
|
||||
uint32_t incl_len; /* number of octets of packet saved in file */
|
||||
uint32_t orig_len; /* actual length of packet */
|
||||
} pcap_rec_hdr_t;
|
||||
|
||||
#define PCAP_MAGIC 0xa1b2c3d4
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t dst_mac[ETHER_ADDR_LEN];
|
||||
uint8_t src_mac[ETHER_ADDR_LEN];
|
||||
uint16_t ethertype;
|
||||
} ether_hdr_t;
|
||||
|
||||
#ifndef ETHERTYPE_IP
|
||||
#define ETHERTYPE_IP 0x0800
|
||||
#endif
|
||||
#ifndef ETHERTYPE_IPV6
|
||||
#define ETHERTYPE_IPV6 0x86dd
|
||||
#endif
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t version_ihl;
|
||||
uint8_t dscp_ecn;
|
||||
uint16_t len;
|
||||
uint16_t id;
|
||||
uint16_t frag;
|
||||
uint8_t ttl;
|
||||
uint8_t proto;
|
||||
uint16_t chksum;
|
||||
uint32_t src_addr;
|
||||
uint32_t dst_addr;
|
||||
} ip4_hdr_t;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t flags;
|
||||
uint16_t len;
|
||||
uint8_t next_hdr;
|
||||
uint8_t hop_limit;
|
||||
uint8_t src_addr[16];
|
||||
uint8_t dst_addr[16];
|
||||
} ip6_hdr_t;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint16_t src_port;
|
||||
uint16_t dst_port;
|
||||
uint32_t seq;
|
||||
uint32_t ack;
|
||||
uint16_t flags;
|
||||
uint16_t win;
|
||||
uint16_t chksum;
|
||||
uint16_t urgp;
|
||||
} tcp_hdr_t;
|
||||
|
||||
#ifndef TH_FIN
|
||||
#define TH_FIN 0x01
|
||||
#endif
|
||||
#ifndef TH_SYN
|
||||
#define TH_SYN 0x02
|
||||
#endif
|
||||
#ifndef TH_RST
|
||||
#define TH_RST 0x04
|
||||
#endif
|
||||
#ifndef TH_PUSH
|
||||
#define TH_PUSH 0x08
|
||||
#endif
|
||||
#ifndef TH_ACK
|
||||
#define TH_ACK 0x10
|
||||
#endif
|
||||
|
||||
/*
|
||||
* *MTU* is the size of the largest layer 3 packet, including IP header.
|
||||
*
|
||||
* *MAX_PKTSZ* is the buffer size needed to construct a layer 2 frame
|
||||
* containing the largest possible layer 3 packet allowed by MTU.
|
||||
*
|
||||
* *MSS_IP4* and *MSS_IP6* are the maximum TCP segment sizes that fit into a
|
||||
* single IPv4 and IPv6 packet, respectively.
|
||||
*
|
||||
* The calculations assume no IPv4 options and no IPv6 option headers.
|
||||
*
|
||||
* These constants are only used for PCAP writing, not for mirroring.
|
||||
*/
|
||||
#define MTU 1500
|
||||
#define MAX_PKTSZ (MTU + sizeof(ether_hdr_t))
|
||||
#define MSS_IP4 (MTU - sizeof(ip4_hdr_t) - sizeof(tcp_hdr_t))
|
||||
#define MSS_IP6 (MTU - sizeof(ip6_hdr_t) - sizeof(tcp_hdr_t))
|
||||
|
||||
/*
|
||||
* IP/TCP checksumming operating on uint32_t intermediate state variable C.
|
||||
*/
|
||||
#define CHKSUM_INIT(C) \
|
||||
{ \
|
||||
(C) = 0; \
|
||||
}
|
||||
#define CHKSUM_ADD_RANGE(C,B,S) \
|
||||
{ \
|
||||
uint16_t *p = (uint16_t *)(B); \
|
||||
size_t words = (S) >> 1; \
|
||||
while (words--) { \
|
||||
(C) += *p++; \
|
||||
} \
|
||||
if ((S) & 1) { \
|
||||
(C) += htons(*((char *)p) << 8); \
|
||||
} \
|
||||
}
|
||||
#define CHKSUM_ADD_UINT32(C,U) \
|
||||
{ \
|
||||
(C) += ((U) >> 16) + ((U) & 0xFFFF); \
|
||||
}
|
||||
#define CHKSUM_ADD_UINT16(C,U) \
|
||||
{ \
|
||||
(C) += (U); \
|
||||
}
|
||||
#define CHKSUM_FINALIZE(C) \
|
||||
{ \
|
||||
(C) = ((C) >> 16) + ((C) & 0xffff); \
|
||||
(C) += ((C) >> 16); \
|
||||
(C) = ~(C); \
|
||||
}
|
||||
|
||||
/* Socket address typecasting shorthand notations. */
|
||||
#define CSA(X) ((const struct sockaddr *)(X))
|
||||
#define CSIN(X) ((const struct sockaddr_in *)(X))
|
||||
#define CSIN6(X) ((const struct sockaddr_in6 *)(X))
|
||||
|
||||
/*
|
||||
* Write the PCAP file-level header to file descriptor *fd* open for writing,
|
||||
* positioned at the beginning of an empty file.
|
||||
*
|
||||
* Returns 0 on success and -1 on failure.
|
||||
*/
|
||||
static int
|
||||
logpkt_write_global_pcap_hdr(int fd)
|
||||
{
|
||||
pcap_file_hdr_t hdr;
|
||||
|
||||
memset(&hdr, 0x0, sizeof(hdr));
|
||||
hdr.magic_number = PCAP_MAGIC;
|
||||
hdr.version_major = 2;
|
||||
hdr.version_minor = 4;
|
||||
hdr.snaplen = MAX_PKTSZ;
|
||||
hdr.network = 1;
|
||||
return write(fd, &hdr, sizeof(hdr)) != sizeof(hdr) ? -1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called on a file descriptor open for reading and writing.
|
||||
* If the fd points to an empty file, a pcap header is added and 0 is returned.
|
||||
* If the fd points to a file with PCAP magic bytes, the file position is moved
|
||||
* to the end of the file and 0 is returned.
|
||||
* If the fd points to a file without PCAP magic bytes, the file is truncated
|
||||
* to zero bytes and a new PCAP header is written.
|
||||
* On a return value of 0, the caller can continue to write PCAP records to the
|
||||
* file descriptor. On error, -1 is returned and the file descriptor is in an
|
||||
* undefined but still open state.
|
||||
*/
|
||||
int
|
||||
logpkt_pcap_open_fd(int fd) {
|
||||
pcap_file_hdr_t hdr;
|
||||
off_t sz;
|
||||
ssize_t n;
|
||||
|
||||
sz = lseek(fd, 0, SEEK_END);
|
||||
if (sz == -1)
|
||||
return -1;
|
||||
|
||||
if (sz > 0) {
|
||||
if (lseek(fd, 0, SEEK_SET) == -1)
|
||||
return -1;
|
||||
n = read(fd, &hdr, sizeof(pcap_file_hdr_t));
|
||||
if (n != sizeof(pcap_file_hdr_t))
|
||||
return -1;
|
||||
if (hdr.magic_number == PCAP_MAGIC)
|
||||
return lseek(fd, 0, SEEK_END) == -1 ? -1 : 0;
|
||||
if (lseek(fd, 0, SEEK_SET) == -1)
|
||||
return -1;
|
||||
if (ftruncate(fd, 0) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return logpkt_write_global_pcap_hdr(fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the per-connection packet crafting context. For mirroring,
|
||||
* *libnet* must be an initialized libnet instance and *mtu* must be the
|
||||
* target interface MTU greater than 0. For PCAP writing, *libnet* must be
|
||||
* NULL and *mtu* must be 0. The ether and sockaddr addresses are used as the
|
||||
* layer 2 and layer 3 addresses respectively. For mirroring, the ethers must
|
||||
* match the actual link layer addresses to be used when sending traffic, not
|
||||
* some emulated addresses.
|
||||
*/
|
||||
void
|
||||
logpkt_ctx_init(logpkt_ctx_t *ctx, libnet_t *libnet, size_t mtu,
|
||||
const uint8_t *src_ether, const uint8_t *dst_ether,
|
||||
const struct sockaddr *src_addr, socklen_t src_addr_len,
|
||||
const struct sockaddr *dst_addr, socklen_t dst_addr_len)
|
||||
{
|
||||
ctx->libnet = libnet;
|
||||
memcpy(ctx->src_ether, src_ether, ETHER_ADDR_LEN);
|
||||
memcpy(ctx->dst_ether, dst_ether, ETHER_ADDR_LEN);
|
||||
memcpy(&ctx->src_addr, src_addr, src_addr_len);
|
||||
memcpy(&ctx->dst_addr, dst_addr, dst_addr_len);
|
||||
ctx->src_seq = 0;
|
||||
ctx->dst_seq = 0;
|
||||
if (mtu) {
|
||||
ctx->mss = mtu - sizeof(tcp_hdr_t)
|
||||
- (dst_addr->sa_family == AF_INET
|
||||
? sizeof(ip4_hdr_t)
|
||||
: sizeof(ip6_hdr_t));
|
||||
} else {
|
||||
ctx->mss = dst_addr->sa_family == AF_INET ? MSS_IP4 : MSS_IP6;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the layer 2 frame contained in *pkt* to file descriptor *fd* already
|
||||
* open for writing. First writes a PCAP record header, then the actual frame.
|
||||
*/
|
||||
static int
|
||||
logpkt_pcap_write(const uint8_t *pkt, size_t pktsz, int fd)
|
||||
{
|
||||
pcap_rec_hdr_t rec_hdr;
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
rec_hdr.ts_sec = tv.tv_sec;
|
||||
rec_hdr.ts_usec = tv.tv_usec;
|
||||
rec_hdr.orig_len = rec_hdr.incl_len = pktsz;
|
||||
|
||||
if (write(fd, &rec_hdr, sizeof(rec_hdr)) != sizeof(rec_hdr)) {
|
||||
log_err_printf("Error writing pcap record hdr: %s\n",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (write(fd, pkt, pktsz) != (ssize_t)pktsz) {
|
||||
log_err_printf("Error writing pcap record: %s\n",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Build a frame from the given layer 2, layer 3 and layer 4 parameters plus
|
||||
* payload, write the resulting bytes into buffer pointed to by *pkt*, and fix
|
||||
* the checksums on all layers. The receiving buffer must be at least
|
||||
* MAX_PKTSZ bytes large and payload must be a maximum of MSS_IP4 or MSS_IP6
|
||||
* respectively. Layer 2 is Ethernet II, layer 3 is IPv4 or IPv6 depending on
|
||||
* the address family of *dst_addr*, and layer 4 is TCP.
|
||||
*
|
||||
* This function is stateless. For header fields that cannot be directly
|
||||
* derived from the arguments, default values will be used.
|
||||
*/
|
||||
static size_t
|
||||
logpkt_pcap_build(uint8_t *pkt,
|
||||
uint8_t *src_ether, uint8_t *dst_ether,
|
||||
const struct sockaddr *src_addr,
|
||||
const struct sockaddr *dst_addr,
|
||||
char flags, uint32_t seq, uint32_t ack,
|
||||
const uint8_t *payload, size_t payloadlen)
|
||||
{
|
||||
ether_hdr_t *ether_hdr;
|
||||
ip4_hdr_t *ip4_hdr;
|
||||
ip6_hdr_t *ip6_hdr;
|
||||
tcp_hdr_t *tcp_hdr;
|
||||
size_t sz;
|
||||
uint32_t sum;
|
||||
|
||||
ether_hdr = (ether_hdr_t *)pkt;
|
||||
memcpy(ether_hdr->src_mac, src_ether, sizeof(ether_hdr->src_mac));
|
||||
memcpy(ether_hdr->dst_mac, dst_ether, sizeof(ether_hdr->dst_mac));
|
||||
sz = sizeof(ether_hdr_t);
|
||||
|
||||
if (dst_addr->sa_family == AF_INET) {
|
||||
ether_hdr->ethertype = htons(ETHERTYPE_IP);
|
||||
ip4_hdr = (ip4_hdr_t *)(((uint8_t *)ether_hdr) +
|
||||
sizeof(ether_hdr_t));
|
||||
ip4_hdr->version_ihl = 0x45;
|
||||
ip4_hdr->dscp_ecn = 0;
|
||||
ip4_hdr->len = htons(sizeof(ip4_hdr_t) +
|
||||
sizeof(tcp_hdr_t) + payloadlen);
|
||||
ip4_hdr->id = sys_rand16(),
|
||||
ip4_hdr->frag = 0;
|
||||
ip4_hdr->ttl = 64;
|
||||
ip4_hdr->proto = IPPROTO_TCP;
|
||||
ip4_hdr->src_addr = CSIN(src_addr)->sin_addr.s_addr;
|
||||
ip4_hdr->dst_addr = CSIN(dst_addr)->sin_addr.s_addr;
|
||||
ip4_hdr->chksum = 0;
|
||||
CHKSUM_INIT(sum);
|
||||
CHKSUM_ADD_RANGE(sum, ip4_hdr, sizeof(ip4_hdr_t));
|
||||
CHKSUM_FINALIZE(sum);
|
||||
ip4_hdr->chksum = sum;
|
||||
sz += sizeof(ip4_hdr_t);
|
||||
tcp_hdr = (tcp_hdr_t *)(((uint8_t *)ip4_hdr) +
|
||||
sizeof(ip4_hdr_t));
|
||||
tcp_hdr->src_port = CSIN(src_addr)->sin_port;
|
||||
tcp_hdr->dst_port = CSIN(dst_addr)->sin_port;
|
||||
/* pseudo header */
|
||||
CHKSUM_INIT(sum);
|
||||
CHKSUM_ADD_UINT32(sum, ip4_hdr->src_addr);
|
||||
CHKSUM_ADD_UINT32(sum, ip4_hdr->dst_addr);
|
||||
CHKSUM_ADD_UINT16(sum, htons(ip4_hdr->proto));
|
||||
CHKSUM_ADD_UINT16(sum, htons(sizeof(tcp_hdr_t) + payloadlen));
|
||||
} else {
|
||||
ether_hdr->ethertype = htons(ETHERTYPE_IPV6);
|
||||
ip6_hdr = (ip6_hdr_t *)(((uint8_t *)ether_hdr) +
|
||||
sizeof(ether_hdr_t));
|
||||
ip6_hdr->flags = htonl(0x60000000UL);
|
||||
ip6_hdr->len = htons(sizeof(tcp_hdr_t) + payloadlen);
|
||||
ip6_hdr->next_hdr = IPPROTO_TCP;
|
||||
ip6_hdr->hop_limit = 255;
|
||||
memcpy(ip6_hdr->src_addr, CSIN6(src_addr)->sin6_addr.s6_addr,
|
||||
sizeof(ip6_hdr->src_addr));
|
||||
memcpy(ip6_hdr->dst_addr, CSIN6(dst_addr)->sin6_addr.s6_addr,
|
||||
sizeof(ip6_hdr->dst_addr));
|
||||
sz += sizeof(ip6_hdr_t);
|
||||
tcp_hdr = (tcp_hdr_t *)(((uint8_t *)ip6_hdr) +
|
||||
sizeof(ip6_hdr_t));
|
||||
tcp_hdr->src_port = CSIN6(src_addr)->sin6_port;
|
||||
tcp_hdr->dst_port = CSIN6(dst_addr)->sin6_port;
|
||||
/* pseudo header */
|
||||
CHKSUM_INIT(sum);
|
||||
CHKSUM_ADD_RANGE(sum, ip6_hdr->src_addr,
|
||||
sizeof(ip6_hdr->src_addr));
|
||||
CHKSUM_ADD_RANGE(sum, ip6_hdr->dst_addr,
|
||||
sizeof(ip6_hdr->dst_addr));
|
||||
CHKSUM_ADD_UINT32(sum, ip6_hdr->len);
|
||||
CHKSUM_ADD_UINT16(sum, htons(IPPROTO_TCP));
|
||||
}
|
||||
tcp_hdr->seq = htonl(seq);
|
||||
tcp_hdr->ack = htonl(ack);
|
||||
tcp_hdr->flags = htons(0x5000|flags);
|
||||
tcp_hdr->win = htons(32767);
|
||||
tcp_hdr->urgp = 0;
|
||||
tcp_hdr->chksum = 0;
|
||||
sz += sizeof(tcp_hdr_t);
|
||||
memcpy(((uint8_t *)tcp_hdr) + sizeof(tcp_hdr_t), payload, payloadlen);
|
||||
CHKSUM_ADD_RANGE(sum, tcp_hdr, sizeof(tcp_hdr_t) + payloadlen);
|
||||
CHKSUM_FINALIZE(sum);
|
||||
tcp_hdr->chksum = sum;
|
||||
return sz + payloadlen;
|
||||
}
|
||||
|
||||
#ifndef WITHOUT_MIRROR
|
||||
/*
|
||||
* Build a packet using libnet intended for mirroring mode. The packet will
|
||||
* be dynamically allocated on the heap by the libnet instance *libnet*.
|
||||
*/
|
||||
static int
|
||||
logpkt_mirror_build(libnet_t *libnet,
|
||||
uint8_t *src_ether, uint8_t *dst_ether,
|
||||
const struct sockaddr *src_addr,
|
||||
const struct sockaddr *dst_addr,
|
||||
char flags, uint32_t seq, uint32_t ack,
|
||||
const uint8_t *payload, size_t payloadlen)
|
||||
{
|
||||
libnet_ptag_t ptag;
|
||||
|
||||
ptag = libnet_build_tcp(src_addr->sa_family == AF_INET
|
||||
? CSIN(src_addr)->sin_port
|
||||
: CSIN6(src_addr)->sin6_port,
|
||||
dst_addr->sa_family == AF_INET
|
||||
? CSIN(dst_addr)->sin_port
|
||||
: CSIN6(dst_addr)->sin6_port,
|
||||
seq,
|
||||
ack,
|
||||
flags,
|
||||
32767, /* window size */
|
||||
0, /* checksum */
|
||||
0, /* urgent pointer */
|
||||
LIBNET_TCP_H + payloadlen,
|
||||
(uint8_t *)payload, payloadlen,
|
||||
libnet, 0);
|
||||
if (ptag == -1) {
|
||||
log_err_printf("Error building tcp header: %s",
|
||||
libnet_geterror(libnet));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dst_addr->sa_family == AF_INET) {
|
||||
ptag = libnet_build_ipv4(LIBNET_IPV4_H + LIBNET_TCP_H +
|
||||
payloadlen,
|
||||
0, /* TOS */
|
||||
(uint16_t)
|
||||
sys_rand16(), /* id */
|
||||
0x4000, /* frag */
|
||||
64, /* TTL */
|
||||
IPPROTO_TCP, /* protocol */
|
||||
0, /* checksum */
|
||||
CSIN(src_addr)->sin_addr.s_addr,
|
||||
CSIN(dst_addr)->sin_addr.s_addr,
|
||||
NULL, 0,
|
||||
libnet, 0);
|
||||
} else {
|
||||
ptag = libnet_build_ipv6(0, /* traffic class */
|
||||
0, /* flow label */
|
||||
LIBNET_IPV6_H + LIBNET_TCP_H +
|
||||
payloadlen,
|
||||
IPPROTO_TCP,
|
||||
255, /* hop limit */
|
||||
*(struct libnet_in6_addr *)
|
||||
&CSIN6(src_addr)->sin6_addr,
|
||||
*(struct libnet_in6_addr *)
|
||||
&CSIN6(dst_addr)->sin6_addr,
|
||||
NULL, 0,
|
||||
libnet, 0);
|
||||
}
|
||||
if (ptag == -1) {
|
||||
log_err_printf("Error building ip header: %s",
|
||||
libnet_geterror(libnet));
|
||||
return -1;
|
||||
}
|
||||
|
||||
ptag = libnet_build_ethernet(dst_ether,
|
||||
src_ether,
|
||||
dst_addr->sa_family == AF_INET
|
||||
? ETHERTYPE_IP : ETHERTYPE_IPV6,
|
||||
NULL, 0,
|
||||
libnet, 0);
|
||||
if (ptag == -1) {
|
||||
log_err_printf("Error building ethernet header: %s",
|
||||
libnet_geterror(libnet));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* !WITHOUT_MIRROR */
|
||||
|
||||
/*
|
||||
* Write a single packet to either PCAP (*fd* != -1) or a network interface
|
||||
* (*fd* == -1). Caller must ensure that *ctx* was initialized accordingly.
|
||||
* The packet will be in direction *direction*, use TCP flags *flags*, and
|
||||
* transmit a payload *payload*. TCP sequence and acknowledgment numbers as
|
||||
* well as source and destination identifiers are taken from *ctx*.
|
||||
*
|
||||
* Caller must ensure that *payload* fits into a frame depending on the MTU
|
||||
* selected (interface in mirroring mode, MTU value in PCAP writing mode).
|
||||
*/
|
||||
static int
|
||||
logpkt_write_packet(logpkt_ctx_t *ctx, int fd, int direction, char flags,
|
||||
const uint8_t *payload, size_t payloadlen)
|
||||
{
|
||||
int rv;
|
||||
|
||||
if (fd != -1) {
|
||||
uint8_t buf[MAX_PKTSZ];
|
||||
size_t sz;
|
||||
if (direction == LOGPKT_REQUEST) {
|
||||
sz = logpkt_pcap_build(buf,
|
||||
ctx->src_ether, ctx->dst_ether,
|
||||
CSA(&ctx->src_addr),
|
||||
CSA(&ctx->dst_addr),
|
||||
flags,
|
||||
ctx->src_seq, ctx->dst_seq,
|
||||
payload, payloadlen);
|
||||
} else {
|
||||
sz = logpkt_pcap_build(buf,
|
||||
ctx->dst_ether, ctx->src_ether,
|
||||
CSA(&ctx->dst_addr),
|
||||
CSA(&ctx->src_addr),
|
||||
flags,
|
||||
ctx->dst_seq, ctx->src_seq,
|
||||
payload, payloadlen);
|
||||
}
|
||||
rv = logpkt_pcap_write(buf, sz, fd);
|
||||
if (rv == -1) {
|
||||
log_err_printf("Error writing packet to PCAP file\n");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
#ifndef WITHOUT_MIRROR
|
||||
/* Source and destination ether are determined by the actual
|
||||
* local MAC address and target MAC address for mirroring the
|
||||
* packets to; use them as-is for both directions. */
|
||||
if (direction == LOGPKT_REQUEST) {
|
||||
rv = logpkt_mirror_build(ctx->libnet,
|
||||
ctx->src_ether, ctx->dst_ether,
|
||||
CSA(&ctx->src_addr),
|
||||
CSA(&ctx->dst_addr),
|
||||
flags,
|
||||
ctx->src_seq, ctx->dst_seq,
|
||||
payload, payloadlen);
|
||||
} else {
|
||||
rv = logpkt_mirror_build(ctx->libnet,
|
||||
ctx->src_ether, ctx->dst_ether,
|
||||
CSA(&ctx->dst_addr),
|
||||
CSA(&ctx->src_addr),
|
||||
flags,
|
||||
ctx->dst_seq, ctx->src_seq,
|
||||
payload, payloadlen);
|
||||
}
|
||||
if (rv == -1) {
|
||||
log_err_printf("Error building packet\n");
|
||||
return -1;
|
||||
}
|
||||
rv = libnet_write(ctx->libnet);
|
||||
if (rv == -1) {
|
||||
log_err_printf("Error writing packet: %s\n",
|
||||
libnet_geterror(ctx->libnet));
|
||||
}
|
||||
libnet_clear_packet(ctx->libnet);
|
||||
#else /* WITHOUT_MIRROR */
|
||||
rv = -1;
|
||||
#endif /* WITHOUT_MIRROR */
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Emulate the initial SYN handshake.
|
||||
*/
|
||||
static int
|
||||
logpkt_write_syn_handshake(logpkt_ctx_t *ctx, int fd)
|
||||
{
|
||||
ctx->src_seq = sys_rand32();
|
||||
if (logpkt_write_packet(ctx, fd, LOGPKT_REQUEST,
|
||||
TH_SYN, NULL, 0) == -1)
|
||||
return -1;
|
||||
ctx->src_seq += 1;
|
||||
ctx->dst_seq = sys_rand32();
|
||||
if (logpkt_write_packet(ctx, fd, LOGPKT_RESPONSE,
|
||||
TH_SYN|TH_ACK, NULL, 0) == -1)
|
||||
return -1;
|
||||
ctx->dst_seq += 1;
|
||||
if (logpkt_write_packet(ctx, fd, LOGPKT_REQUEST,
|
||||
TH_ACK, NULL, 0) == -1)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Emulate the necessary packets to write a single payload segment. If
|
||||
* necessary, a SYN handshake will automatically be generated before emitting
|
||||
* the packet carrying the payload plus a matching ACK.
|
||||
*/
|
||||
int
|
||||
logpkt_write_payload(logpkt_ctx_t *ctx, int fd, int direction,
|
||||
const uint8_t *payload, size_t payloadlen)
|
||||
{
|
||||
int other_direction = (direction == LOGPKT_REQUEST) ? LOGPKT_RESPONSE
|
||||
: LOGPKT_REQUEST;
|
||||
|
||||
if (ctx->src_seq == 0) {
|
||||
if (logpkt_write_syn_handshake(ctx, fd) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (payloadlen > 0) {
|
||||
size_t n = payloadlen > ctx->mss ? ctx->mss : payloadlen;
|
||||
if (logpkt_write_packet(ctx, fd, direction,
|
||||
TH_PUSH|TH_ACK, payload, n) == -1) {
|
||||
log_err_printf("Warning: Failed to write to pcap log"
|
||||
": %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (direction == LOGPKT_REQUEST) {
|
||||
ctx->src_seq += n;
|
||||
} else {
|
||||
ctx->dst_seq += n;
|
||||
}
|
||||
payload += n;
|
||||
payloadlen -= n;
|
||||
}
|
||||
|
||||
if (logpkt_write_packet(ctx, fd, other_direction,
|
||||
TH_ACK, NULL, 0) == -1) {
|
||||
log_err_printf("Warning: Failed to write to pcap log: %s\n",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Emulate a connection close, emitting a FIN handshake in the correct
|
||||
* direction. Does not close the file descriptor.
|
||||
*/
|
||||
int
|
||||
logpkt_write_close(logpkt_ctx_t *ctx, int fd, int direction) {
|
||||
int other_direction = (direction == LOGPKT_REQUEST) ? LOGPKT_RESPONSE
|
||||
: LOGPKT_REQUEST;
|
||||
|
||||
if (ctx->src_seq == 0) {
|
||||
if (logpkt_write_syn_handshake(ctx, fd) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (logpkt_write_packet(ctx, fd, direction,
|
||||
TH_FIN|TH_ACK, NULL, 0) == -1) {
|
||||
log_err_printf("Warning: Failed to write packet\n");
|
||||
return -1;
|
||||
}
|
||||
if (direction == LOGPKT_REQUEST) {
|
||||
ctx->src_seq += 1;
|
||||
} else {
|
||||
ctx->dst_seq += 1;
|
||||
}
|
||||
|
||||
if (logpkt_write_packet(ctx, fd, other_direction,
|
||||
TH_FIN|TH_ACK, NULL, 0) == -1) {
|
||||
log_err_printf("Warning: Failed to write packet\n");
|
||||
return -1;
|
||||
}
|
||||
if (other_direction == LOGPKT_REQUEST) {
|
||||
ctx->src_seq += 1;
|
||||
} else {
|
||||
ctx->dst_seq += 1;
|
||||
}
|
||||
|
||||
if (logpkt_write_packet(ctx, fd, direction,
|
||||
TH_ACK, NULL, 0) == -1) {
|
||||
log_err_printf("Warning: Failed to write packet\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef WITHOUT_MIRROR
|
||||
typedef struct {
|
||||
uint32_t ip;
|
||||
int result;
|
||||
uint8_t ether[ETHER_ADDR_LEN];
|
||||
} logpkt_recv_arp_reply_ctx_t;
|
||||
|
||||
/*
|
||||
* Receive a single ARP reply and copy the resulting ether to ctx->ether.
|
||||
*/
|
||||
static void
|
||||
logpkt_recv_arp_reply(uint8_t *user,
|
||||
UNUSED const struct pcap_pkthdr *h,
|
||||
const uint8_t *packet)
|
||||
{
|
||||
logpkt_recv_arp_reply_ctx_t *ctx = (logpkt_recv_arp_reply_ctx_t*)user;
|
||||
struct libnet_802_3_hdr *heth = (void*)packet;
|
||||
struct libnet_arp_hdr *harp = (void*)((char*)heth + LIBNET_ETH_H);
|
||||
|
||||
/* skip if wrong protocol */
|
||||
if (htons(harp->ar_op) != ARPOP_REPLY)
|
||||
return;
|
||||
if (htons(harp->ar_pro) != ETHERTYPE_IP)
|
||||
return;
|
||||
if (htons(harp->ar_hrd) != ARPHRD_ETHER)
|
||||
return;
|
||||
|
||||
/* skip if wrong target IP address */
|
||||
if (!!memcmp(&ctx->ip, (char*)harp + harp->ar_hln + LIBNET_ARP_H, 4))
|
||||
return;
|
||||
|
||||
/* skip if source ether mismatch */
|
||||
if (!!memcmp((u_char*)harp + sizeof(struct libnet_arp_hdr),
|
||||
heth->_802_3_shost, ETHER_ADDR_LEN))
|
||||
return;
|
||||
|
||||
memcpy(ctx->ether,
|
||||
(u_char*)harp + sizeof(struct libnet_arp_hdr),
|
||||
ETHER_ADDR_LEN);
|
||||
ctx->result = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up the appropriate source and destination ethernet addresses for
|
||||
* mirroring packets to dst_ip_s on interface dst_if_s.
|
||||
* Only IPv4 mirror targets are supported.
|
||||
*/
|
||||
int
|
||||
logpkt_ether_lookup(libnet_t *libnet,
|
||||
uint8_t *src_ether, uint8_t *dst_ether,
|
||||
const char *dst_ip_s, const char *dst_if_s)
|
||||
{
|
||||
char errbuf[PCAP_ERRBUF_SIZE];
|
||||
uint8_t broadcast_ether[ETHER_ADDR_LEN] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
uint8_t zero_ether[ETHER_ADDR_LEN] = {
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
|
||||
struct libnet_ether_addr *src_ether_addr;
|
||||
uint32_t src_ip;
|
||||
struct bpf_program bp;
|
||||
int count = 50;
|
||||
logpkt_recv_arp_reply_ctx_t ctx;
|
||||
|
||||
if (sys_get_af(dst_ip_s) != AF_INET) {
|
||||
log_err_printf("Mirroring target must be an IPv4 address.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx.result = -1;
|
||||
ctx.ip = libnet_name2addr4(libnet, (char *)dst_ip_s,
|
||||
LIBNET_DONT_RESOLVE);
|
||||
if (ctx.ip == (uint32_t)-1) {
|
||||
log_err_printf("Error converting dst IP address: %s\n",
|
||||
libnet_geterror(libnet));
|
||||
goto out;
|
||||
}
|
||||
src_ip = libnet_get_ipaddr4(libnet);
|
||||
if (src_ip == (uint32_t)-1) {
|
||||
log_err_printf("Error getting src IP address: %s\n",
|
||||
libnet_geterror(libnet));
|
||||
goto out;
|
||||
}
|
||||
src_ether_addr = libnet_get_hwaddr(libnet);
|
||||
if (src_ether_addr == NULL) {
|
||||
log_err_printf("Error getting src ethernet address: %s\n",
|
||||
libnet_geterror(libnet));
|
||||
goto out;
|
||||
}
|
||||
memcpy(src_ether, src_ether_addr->ether_addr_octet, ETHER_ADDR_LEN);
|
||||
|
||||
if (libnet_autobuild_arp(ARPOP_REQUEST,
|
||||
src_ether,
|
||||
(uint8_t*)&src_ip,
|
||||
zero_ether,
|
||||
(uint8_t*)&ctx.ip,
|
||||
libnet) == -1) {
|
||||
log_err_printf("Error building arp header: %s\n",
|
||||
libnet_geterror(libnet));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (libnet_autobuild_ethernet(broadcast_ether,
|
||||
ETHERTYPE_ARP,
|
||||
libnet) == -1) {
|
||||
log_err_printf("Error building ethernet header: %s",
|
||||
libnet_geterror(libnet));
|
||||
goto out;
|
||||
}
|
||||
|
||||
pcap_t *pcap = pcap_open_live(dst_if_s, 100, 0, 10, errbuf);
|
||||
if (pcap == NULL) {
|
||||
log_err_printf("Error in pcap_open_live(): %s\n", errbuf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (pcap_compile(pcap, &bp, "arp", 0, -1) == -1) {
|
||||
log_err_printf("Error in pcap_compile(): %s\n",
|
||||
pcap_geterr(pcap));
|
||||
goto out2;
|
||||
}
|
||||
if (pcap_setfilter(pcap, &bp) == -1) {
|
||||
log_err_printf("Error in pcap_setfilter(): %s\n",
|
||||
pcap_geterr(pcap));
|
||||
goto out3;
|
||||
}
|
||||
|
||||
do {
|
||||
if (libnet_write(libnet) != -1) {
|
||||
/* Limit # of packets to process, so we can loop to
|
||||
* send arp requests on busy networks. */
|
||||
if (pcap_dispatch(pcap, 1000,
|
||||
(pcap_handler)logpkt_recv_arp_reply,
|
||||
(u_char*)&ctx) < 0) {
|
||||
log_err_printf("Error in pcap_dispatch(): %s\n",
|
||||
pcap_geterr(pcap));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
log_err_printf("Error writing arp packet: %s",
|
||||
libnet_geterror(libnet));
|
||||
break;
|
||||
}
|
||||
sleep(1);
|
||||
} while (ctx.result == -1 && --count > 0);
|
||||
|
||||
if (ctx.result == 0) {
|
||||
memcpy(dst_ether, &ctx.ether, ETHER_ADDR_LEN);
|
||||
log_dbg_printf("Mirror target is up: "
|
||||
"%02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
dst_ether[0], dst_ether[1], dst_ether[2],
|
||||
dst_ether[3], dst_ether[4], dst_ether[5]);
|
||||
}
|
||||
|
||||
out3:
|
||||
pcap_freecode(&bp);
|
||||
out2:
|
||||
pcap_close(pcap);
|
||||
out:
|
||||
libnet_clear_packet(libnet);
|
||||
return ctx.result;
|
||||
}
|
||||
#endif /* !WITHOUT_MIRROR */
|
||||
|
||||
/* vim: set noet ft=c: */
|
@ -0,0 +1,70 @@
|
||||
/*-
|
||||
* SSLsplit - transparent SSL/TLS interception
|
||||
* https://www.roe.ch/SSLsplit
|
||||
*
|
||||
* Copyright (c) 2009-2018, Daniel Roethlisberger <daniel@roe.ch>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LOGPKT_H
|
||||
#define LOGPKT_H
|
||||
|
||||
#include "attrib.h"
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifndef WITHOUT_MIRROR
|
||||
#include <libnet.h>
|
||||
#else /* WITHOUT_MIRROR */
|
||||
#define libnet_t void
|
||||
#define ETHER_ADDR_LEN 6
|
||||
#endif /* WITHOUT_MIRROR */
|
||||
|
||||
typedef struct {
|
||||
libnet_t *libnet;
|
||||
uint8_t src_ether[ETHER_ADDR_LEN];
|
||||
uint8_t dst_ether[ETHER_ADDR_LEN];
|
||||
struct sockaddr_storage src_addr;
|
||||
struct sockaddr_storage dst_addr;
|
||||
uint32_t src_seq;
|
||||
uint32_t dst_seq;
|
||||
size_t mss;
|
||||
} logpkt_ctx_t;
|
||||
|
||||
#define LOGPKT_REQUEST 0
|
||||
#define LOGPKT_RESPONSE 1
|
||||
|
||||
int logpkt_pcap_open_fd(int fd) WUNRES;
|
||||
void logpkt_ctx_init(logpkt_ctx_t *, libnet_t *, size_t,
|
||||
const uint8_t *, const uint8_t *,
|
||||
const struct sockaddr *, socklen_t,
|
||||
const struct sockaddr *, socklen_t);
|
||||
int logpkt_write_payload(logpkt_ctx_t *, int, int,
|
||||
const unsigned char *, size_t) WUNRES;
|
||||
int logpkt_write_close(logpkt_ctx_t *, int, int);
|
||||
int logpkt_ether_lookup(libnet_t *, uint8_t *, uint8_t *,
|
||||
const char *, const char *) WUNRES;
|
||||
|
||||
#endif /* !LOGPKT_H */
|
@ -0,0 +1,367 @@
|
||||
APPLE PUBLIC SOURCE LICENSE
|
||||
Version 2.0 - August 6, 2003
|
||||
|
||||
Please read this License carefully before downloading this software.
|
||||
By downloading or using this software, you are agreeing to be bound by
|
||||
the terms of this License. If you do not or cannot agree to the terms
|
||||
of this License, please do not download or use the software.
|
||||
|
||||
1. General; Definitions. This License applies to any program or other
|
||||
work which Apple Computer, Inc. ("Apple") makes publicly available and
|
||||
which contains a notice placed by Apple identifying such program or
|
||||
work as "Original Code" and stating that it is subject to the terms of
|
||||
this Apple Public Source License version 2.0 ("License"). As used in
|
||||
this License:
|
||||
|
||||
1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is
|
||||
the grantor of rights, (i) claims of patents that are now or hereafter
|
||||
acquired, owned by or assigned to Apple and (ii) that cover subject
|
||||
matter contained in the Original Code, but only to the extent
|
||||
necessary to use, reproduce and/or distribute the Original Code
|
||||
without infringement; and (b) in the case where You are the grantor of
|
||||
rights, (i) claims of patents that are now or hereafter acquired,
|
||||
owned by or assigned to You and (ii) that cover subject matter in Your
|
||||
Modifications, taken alone or in combination with Original Code.
|
||||
|
||||
1.2 "Contributor" means any person or entity that creates or
|
||||
contributes to the creation of Modifications.
|
||||
|
||||
1.3 "Covered Code" means the Original Code, Modifications, the
|
||||
combination of Original Code and any Modifications, and/or any
|
||||
respective portions thereof.
|
||||
|
||||
1.4 "Externally Deploy" means: (a) to sublicense, distribute or
|
||||
otherwise make Covered Code available, directly or indirectly, to
|
||||
anyone other than You; and/or (b) to use Covered Code, alone or as
|
||||
part of a Larger Work, in any way to provide a service, including but
|
||||
not limited to delivery of content, through electronic communication
|
||||
with a client other than You.
|
||||
|
||||
1.5 "Larger Work" means a work which combines Covered Code or portions
|
||||
thereof with code not governed by the terms of this License.
|
||||
|
||||
1.6 "Modifications" mean any addition to, deletion from, and/or change
|
||||
to, the substance and/or structure of the Original Code, any previous
|
||||
Modifications, the combination of Original Code and any previous
|
||||
Modifications, and/or any respective portions thereof. When code is
|
||||
released as a series of files, a Modification is: (a) any addition to
|
||||
or deletion from the contents of a file containing Covered Code;
|
||||
and/or (b) any new file or other representation of computer program
|
||||
statements that contains any part of Covered Code.
|
||||
|
||||
1.7 "Original Code" means (a) the Source Code of a program or other
|
||||
work as originally made available by Apple under this License,
|
||||
including the Source Code of any updates or upgrades to such programs
|
||||
or works made available by Apple under this License, and that has been
|
||||
expressly identified by Apple as such in the header file(s) of such
|
||||
work; and (b) the object code compiled from such Source Code and
|
||||
originally made available by Apple under this License.
|
||||
|
||||
1.8 "Source Code" means the human readable form of a program or other
|
||||
work that is suitable for making modifications to it, including all
|
||||
modules it contains, plus any associated interface definition files,
|
||||
scripts used to control compilation and installation of an executable
|
||||
(object code).
|
||||
|
||||
1.9 "You" or "Your" means an individual or a legal entity exercising
|
||||
rights under this License. For legal entities, "You" or "Your"
|
||||
includes any entity which controls, is controlled by, or is under
|
||||
common control with, You, where "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of fifty percent
|
||||
(50%) or more of the outstanding shares or beneficial ownership of
|
||||
such entity.
|
||||
|
||||
2. Permitted Uses; Conditions & Restrictions. Subject to the terms
|
||||
and conditions of this License, Apple hereby grants You, effective on
|
||||
the date You accept this License and download the Original Code, a
|
||||
world-wide, royalty-free, non-exclusive license, to the extent of
|
||||
Apple's Applicable Patent Rights and copyrights covering the Original
|
||||
Code, to do the following:
|
||||
|
||||
2.1 Unmodified Code. You may use, reproduce, display, perform,
|
||||
internally distribute within Your organization, and Externally Deploy
|
||||
verbatim, unmodified copies of the Original Code, for commercial or
|
||||
non-commercial purposes, provided that in each instance:
|
||||
|
||||
(a) You must retain and reproduce in all copies of Original Code the
|
||||
copyright and other proprietary notices and disclaimers of Apple as
|
||||
they appear in the Original Code, and keep intact all notices in the
|
||||
Original Code that refer to this License; and
|
||||
|
||||
(b) You must include a copy of this License with every copy of Source
|
||||
Code of Covered Code and documentation You distribute or Externally
|
||||
Deploy, and You may not offer or impose any terms on such Source Code
|
||||
that alter or restrict this License or the recipients' rights
|
||||
hereunder, except as permitted under Section 6.
|
||||
|
||||
2.2 Modified Code. You may modify Covered Code and use, reproduce,
|
||||
display, perform, internally distribute within Your organization, and
|
||||
Externally Deploy Your Modifications and Covered Code, for commercial
|
||||
or non-commercial purposes, provided that in each instance You also
|
||||
meet all of these conditions:
|
||||
|
||||
(a) You must satisfy all the conditions of Section 2.1 with respect to
|
||||
the Source Code of the Covered Code;
|
||||
|
||||
(b) You must duplicate, to the extent it does not already exist, the
|
||||
notice in Exhibit A in each file of the Source Code of all Your
|
||||
Modifications, and cause the modified files to carry prominent notices
|
||||
stating that You changed the files and the date of any change; and
|
||||
|
||||
(c) If You Externally Deploy Your Modifications, You must make
|
||||
Source Code of all Your Externally Deployed Modifications either
|
||||
available to those to whom You have Externally Deployed Your
|
||||
Modifications, or publicly available. Source Code of Your Externally
|
||||
Deployed Modifications must be released under the terms set forth in
|
||||
this License, including the license grants set forth in Section 3
|
||||
below, for as long as you Externally Deploy the Covered Code or twelve
|
||||
(12) months from the date of initial External Deployment, whichever is
|
||||
longer. You should preferably distribute the Source Code of Your
|
||||
Externally Deployed Modifications electronically (e.g. download from a
|
||||
web site).
|
||||
|
||||
2.3 Distribution of Executable Versions. In addition, if You
|
||||
Externally Deploy Covered Code (Original Code and/or Modifications) in
|
||||
object code, executable form only, You must include a prominent
|
||||
notice, in the code itself as well as in related documentation,
|
||||
stating that Source Code of the Covered Code is available under the
|
||||
terms of this License with information on how and where to obtain such
|
||||
Source Code.
|
||||
|
||||
2.4 Third Party Rights. You expressly acknowledge and agree that
|
||||
although Apple and each Contributor grants the licenses to their
|
||||
respective portions of the Covered Code set forth herein, no
|
||||
assurances are provided by Apple or any Contributor that the Covered
|
||||
Code does not infringe the patent or other intellectual property
|
||||
rights of any other entity. Apple and each Contributor disclaim any
|
||||
liability to You for claims brought by any other entity based on
|
||||
infringement of intellectual property rights or otherwise. As a
|
||||
condition to exercising the rights and licenses granted hereunder, You
|
||||
hereby assume sole responsibility to secure any other intellectual
|
||||
property rights needed, if any. For example, if a third party patent
|
||||
license is required to allow You to distribute the Covered Code, it is
|
||||
Your responsibility to acquire that license before distributing the
|
||||
Covered Code.
|
||||
|
||||
3. Your Grants. In consideration of, and as a condition to, the
|
||||
licenses granted to You under this License, You hereby grant to any
|
||||
person or entity receiving or distributing Covered Code under this
|
||||
License a non-exclusive, royalty-free, perpetual, irrevocable license,
|
||||
under Your Applicable Patent Rights and other intellectual property
|
||||
rights (other than patent) owned or controlled by You, to use,
|
||||
reproduce, display, perform, modify, sublicense, distribute and
|
||||
Externally Deploy Your Modifications of the same scope and extent as
|
||||
Apple's licenses under Sections 2.1 and 2.2 above.
|
||||
|
||||
4. Larger Works. You may create a Larger Work by combining Covered
|
||||
Code with other code not governed by the terms of this License and
|
||||
distribute the Larger Work as a single product. In each such instance,
|
||||
You must make sure the requirements of this License are fulfilled for
|
||||
the Covered Code or any portion thereof.
|
||||
|
||||
5. Limitations on Patent License. Except as expressly stated in
|
||||
Section 2, no other patent rights, express or implied, are granted by
|
||||
Apple herein. Modifications and/or Larger Works may require additional
|
||||
patent licenses from Apple which Apple may grant in its sole
|
||||
discretion.
|
||||
|
||||
6. Additional Terms. You may choose to offer, and to charge a fee for,
|
||||
warranty, support, indemnity or liability obligations and/or other
|
||||
rights consistent with the scope of the license granted herein
|
||||
("Additional Terms") to one or more recipients of Covered Code.
|
||||
However, You may do so only on Your own behalf and as Your sole
|
||||
responsibility, and not on behalf of Apple or any Contributor. You
|
||||
must obtain the recipient's agreement that any such Additional Terms
|
||||
are offered by You alone, and You hereby agree to indemnify, defend
|
||||
and hold Apple and every Contributor harmless for any liability
|
||||
incurred by or claims asserted against Apple or such Contributor by
|
||||
reason of any such Additional Terms.
|
||||
|
||||
7. Versions of the License. Apple may publish revised and/or new
|
||||
versions of this License from time to time. Each version will be given
|
||||
a distinguishing version number. Once Original Code has been published
|
||||
under a particular version of this License, You may continue to use it
|
||||
under the terms of that version. You may also choose to use such
|
||||
Original Code under the terms of any subsequent version of this
|
||||
License published by Apple. No one other than Apple has the right to
|
||||
modify the terms applicable to Covered Code created under this
|
||||
License.
|
||||
|
||||
8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in
|
||||
part pre-release, untested, or not fully tested works. The Covered
|
||||
Code may contain errors that could cause failures or loss of data, and
|
||||
may be incomplete or contain inaccuracies. You expressly acknowledge
|
||||
and agree that use of the Covered Code, or any portion thereof, is at
|
||||
Your sole and entire risk. THE COVERED CODE IS PROVIDED "AS IS" AND
|
||||
WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND AND APPLE AND
|
||||
APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE
|
||||
PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM
|
||||
ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT
|
||||
NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF
|
||||
MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR
|
||||
PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD
|
||||
PARTY RIGHTS. APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST
|
||||
INTERFERENCE WITH YOUR ENJOYMENT OF THE COVERED CODE, THAT THE
|
||||
FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR REQUIREMENTS,
|
||||
THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR
|
||||
ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO
|
||||
ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE
|
||||
AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY.
|
||||
You acknowledge that the Covered Code is not intended for use in the
|
||||
operation of nuclear facilities, aircraft navigation, communication
|
||||
systems, or air traffic control machines in which case the failure of
|
||||
the Covered Code could lead to death, personal injury, or severe
|
||||
physical or environmental damage.
|
||||
|
||||
9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO
|
||||
EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL,
|
||||
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING
|
||||
TO THIS LICENSE OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR
|
||||
ANY PORTION THEREOF, WHETHER UNDER A THEORY OF CONTRACT, WARRANTY,
|
||||
TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF
|
||||
APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY
|
||||
REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF
|
||||
INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY
|
||||
TO YOU. In no event shall Apple's total liability to You for all
|
||||
damages (other than as may be required by applicable law) under this
|
||||
License exceed the amount of fifty dollars ($50.00).
|
||||
|
||||
10. Trademarks. This License does not grant any rights to use the
|
||||
trademarks or trade names "Apple", "Apple Computer", "Mac", "Mac OS",
|
||||
"QuickTime", "QuickTime Streaming Server" or any other trademarks,
|
||||
service marks, logos or trade names belonging to Apple (collectively
|
||||
"Apple Marks") or to any trademark, service mark, logo or trade name
|
||||
belonging to any Contributor. You agree not to use any Apple Marks in
|
||||
or as part of the name of products derived from the Original Code or
|
||||
to endorse or promote products derived from the Original Code other
|
||||
than as expressly permitted by and in strict compliance at all times
|
||||
with Apple's third party trademark usage guidelines which are posted
|
||||
at http://www.apple.com/legal/guidelinesfor3rdparties.html.
|
||||
|
||||
11. Ownership. Subject to the licenses granted under this License,
|
||||
each Contributor retains all rights, title and interest in and to any
|
||||
Modifications made by such Contributor. Apple retains all rights,
|
||||
title and interest in and to the Original Code and any Modifications
|
||||
made by or on behalf of Apple ("Apple Modifications"), and such Apple
|
||||
Modifications will not be automatically subject to this License. Apple
|
||||
may, at its sole discretion, choose to license such Apple
|
||||
Modifications under this License, or on different terms from those
|
||||
contained in this License or may choose not to license them at all.
|
||||
|
||||
12. Termination.
|
||||
|
||||
12.1 Termination. This License and the rights granted hereunder will
|
||||
terminate:
|
||||
|
||||
(a) automatically without notice from Apple if You fail to comply with
|
||||
any term(s) of this License and fail to cure such breach within 30
|
||||
days of becoming aware of such breach;
|
||||
|
||||
(b) immediately in the event of the circumstances described in Section
|
||||
13.5(b); or
|
||||
|
||||
(c) automatically without notice from Apple if You, at any time during
|
||||
the term of this License, commence an action for patent infringement
|
||||
against Apple; provided that Apple did not first commence
|
||||
an action for patent infringement against You in that instance.
|
||||
|
||||
12.2 Effect of Termination. Upon termination, You agree to immediately
|
||||
stop any further use, reproduction, modification, sublicensing and
|
||||
distribution of the Covered Code. All sublicenses to the Covered Code
|
||||
which have been properly granted prior to termination shall survive
|
||||
any termination of this License. Provisions which, by their nature,
|
||||
should remain in effect beyond the termination of this License shall
|
||||
survive, including but not limited to Sections 3, 5, 8, 9, 10, 11,
|
||||
12.2 and 13. No party will be liable to any other for compensation,
|
||||
indemnity or damages of any sort solely as a result of terminating
|
||||
this License in accordance with its terms, and termination of this
|
||||
License will be without prejudice to any other right or remedy of
|
||||
any party.
|
||||
|
||||
13. Miscellaneous.
|
||||
|
||||
13.1 Government End Users. The Covered Code is a "commercial item" as
|
||||
defined in FAR 2.101. Government software and technical data rights in
|
||||
the Covered Code include only those rights customarily provided to the
|
||||
public as defined in this License. This customary commercial license
|
||||
in technical data and software is provided in accordance with FAR
|
||||
12.211 (Technical Data) and 12.212 (Computer Software) and, for
|
||||
Department of Defense purchases, DFAR 252.227-7015 (Technical Data --
|
||||
Commercial Items) and 227.7202-3 (Rights in Commercial Computer
|
||||
Software or Computer Software Documentation). Accordingly, all U.S.
|
||||
Government End Users acquire Covered Code with only those rights set
|
||||
forth herein.
|
||||
|
||||
13.2 Relationship of Parties. This License will not be construed as
|
||||
creating an agency, partnership, joint venture or any other form of
|
||||
legal association between or among You, Apple or any Contributor, and
|
||||
You will not represent to the contrary, whether expressly, by
|
||||
implication, appearance or otherwise.
|
||||
|
||||
13.3 Independent Development. Nothing in this License will impair
|
||||
Apple's right to acquire, license, develop, have others develop for
|
||||
it, market and/or distribute technology or products that perform the
|
||||
same or similar functions as, or otherwise compete with,
|
||||
Modifications, Larger Works, technology or products that You may
|
||||
develop, produce, market or distribute.
|
||||
|
||||
13.4 Waiver; Construction. Failure by Apple or any Contributor to
|
||||
enforce any provision of this License will not be deemed a waiver of
|
||||
future enforcement of that or any other provision. Any law or
|
||||
regulation which provides that the language of a contract shall be
|
||||
construed against the drafter will not apply to this License.
|
||||
|
||||
13.5 Severability. (a) If for any reason a court of competent
|
||||
jurisdiction finds any provision of this License, or portion thereof,
|
||||
to be unenforceable, that provision of the License will be enforced to
|
||||
the maximum extent permissible so as to effect the economic benefits
|
||||
and intent of the parties, and the remainder of this License will
|
||||
continue in full force and effect. (b) Notwithstanding the foregoing,
|
||||
if applicable law prohibits or restricts You from fully and/or
|
||||
specifically complying with Sections 2 and/or 3 or prevents the
|
||||
enforceability of either of those Sections, this License will
|
||||
immediately terminate and You must immediately discontinue any use of
|
||||
the Covered Code and destroy all copies of it that are in your
|
||||
possession or control.
|
||||
|
||||
13.6 Dispute Resolution. Any litigation or other dispute resolution
|
||||
between You and Apple relating to this License shall take place in the
|
||||
Northern District of California, and You and Apple hereby consent to
|
||||
the personal jurisdiction of, and venue in, the state and federal
|
||||
courts within that District with respect to this License. The
|
||||
application of the United Nations Convention on Contracts for the
|
||||
International Sale of Goods is expressly excluded.
|
||||
|
||||
13.7 Entire Agreement; Governing Law. This License constitutes the
|
||||
entire agreement between the parties with respect to the subject
|
||||
matter hereof. This License shall be governed by the laws of the
|
||||
United States and the State of California, except that body of
|
||||
California law concerning conflicts of law.
|
||||
|
||||
Where You are located in the province of Quebec, Canada, the following
|
||||
clause applies: The parties hereby confirm that they have requested
|
||||
that this License and all related documents be drafted in English. Les
|
||||
parties ont exige que le present contrat et tous les documents
|
||||
connexes soient rediges en anglais.
|
||||
|
||||
EXHIBIT A.
|
||||
|
||||
"Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
|
||||
Reserved.
|
||||
|
||||
This file contains Original Code and/or Modifications of Original Code
|
||||
as defined in and that are subject to the Apple Public Source License
|
||||
Version 2.0 (the 'License'). You may not use this file except in
|
||||
compliance with the License. Please obtain a copy of the License at
|
||||
http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
file.
|
||||
|
||||
The Original Code and all software distributed under the License are
|
||||
distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
Please see the License for the specific language governing rights and
|
||||
limitations under the License."
|
@ -0,0 +1,802 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2010 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. The rights granted to you under the License
|
||||
* may not be used to create, or enable the creation or redistribution of,
|
||||
* unlawful or unlicensed copies of an Apple operating system, or to
|
||||
* circumvent, violate, or enable the circumvention or violation of, any
|
||||
* terms of an Apple operating system software license agreement.
|
||||
*
|
||||
* Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
/* $NetBSD: tree.h,v 1.13 2006/08/27 22:32:38 christos Exp $ */
|
||||
/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */
|
||||
/*
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _LIBKERN_TREE_H_
|
||||
#define _LIBKERN_TREE_H_
|
||||
|
||||
/*
|
||||
* This file defines data structures for different types of trees:
|
||||
* splay trees and red-black trees.
|
||||
*
|
||||
* A splay tree is a self-organizing data structure. Every operation
|
||||
* on the tree causes a splay to happen. The splay moves the requested
|
||||
* node to the root of the tree and partly rebalances it.
|
||||
*
|
||||
* This has the benefit that request locality causes faster lookups as
|
||||
* the requested nodes move to the top of the tree. On the other hand,
|
||||
* every lookup causes memory writes.
|
||||
*
|
||||
* The Balance Theorem bounds the total access time for m operations
|
||||
* and n inserts on an initially empty tree as O((m + n)lg n). The
|
||||
* amortized cost for a sequence of m accesses to a splay tree is O(lg n);
|
||||
*
|
||||
* A red-black tree is a binary search tree with the node color as an
|
||||
* extra attribute. It fulfills a set of conditions:
|
||||
* - every search path from the root to a leaf consists of the
|
||||
* same number of black nodes,
|
||||
* - each red node (except for the root) has a black parent,
|
||||
* - each leaf node is black.
|
||||
*
|
||||
* Every operation on a red-black tree is bounded as O(lg n).
|
||||
* The maximum height of a red-black tree is 2lg (n+1).
|
||||
*/
|
||||
|
||||
#define SPLAY_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *sph_root; /* root of the tree */ \
|
||||
}
|
||||
|
||||
#define SPLAY_INITIALIZER(root) \
|
||||
{ NULL }
|
||||
|
||||
#define SPLAY_INIT(root) do { \
|
||||
(root)->sph_root = NULL; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *spe_left; /* left element */ \
|
||||
struct type *spe_right; /* right element */ \
|
||||
}
|
||||
|
||||
#define SPLAY_LEFT(elm, field) (elm)->field.spe_left
|
||||
#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right
|
||||
#define SPLAY_ROOT(head) (head)->sph_root
|
||||
#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL)
|
||||
|
||||
/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
|
||||
#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \
|
||||
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
|
||||
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
|
||||
(head)->sph_root = tmp; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
|
||||
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
|
||||
(head)->sph_root = tmp; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_LINKLEFT(head, tmp, field) do { \
|
||||
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
|
||||
tmp = (head)->sph_root; \
|
||||
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_LINKRIGHT(head, tmp, field) do { \
|
||||
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
|
||||
tmp = (head)->sph_root; \
|
||||
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
|
||||
SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
|
||||
SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
|
||||
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
/* Generates prototypes and inline functions */
|
||||
|
||||
#define SPLAY_PROTOTYPE(name, type, field, cmp) \
|
||||
void name##_SPLAY(struct name *, struct type *); \
|
||||
void name##_SPLAY_MINMAX(struct name *, int); \
|
||||
struct type *name##_SPLAY_INSERT(struct name *, struct type *); \
|
||||
struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \
|
||||
\
|
||||
/* Finds the node with the same key as elm */ \
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_FIND(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
if (SPLAY_EMPTY(head)) \
|
||||
return(NULL); \
|
||||
name##_SPLAY(head, elm); \
|
||||
if ((cmp)(elm, (head)->sph_root) == 0) \
|
||||
return (head->sph_root); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_NEXT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
name##_SPLAY(head, elm); \
|
||||
if (SPLAY_RIGHT(elm, field) != NULL) { \
|
||||
elm = SPLAY_RIGHT(elm, field); \
|
||||
while (SPLAY_LEFT(elm, field) != NULL) { \
|
||||
elm = SPLAY_LEFT(elm, field); \
|
||||
} \
|
||||
} else \
|
||||
elm = NULL; \
|
||||
return (elm); \
|
||||
} \
|
||||
\
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_MIN_MAX(struct name *head, int val) \
|
||||
{ \
|
||||
name##_SPLAY_MINMAX(head, val); \
|
||||
return (SPLAY_ROOT(head)); \
|
||||
}
|
||||
|
||||
/* Main splay operation.
|
||||
* Moves node close to the key of elm to top
|
||||
*/
|
||||
#define SPLAY_GENERATE(name, type, field, cmp) \
|
||||
struct type * \
|
||||
name##_SPLAY_INSERT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
if (SPLAY_EMPTY(head)) { \
|
||||
SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \
|
||||
} else { \
|
||||
int __comp; \
|
||||
name##_SPLAY(head, elm); \
|
||||
__comp = (cmp)(elm, (head)->sph_root); \
|
||||
if(__comp < 0) { \
|
||||
SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
|
||||
SPLAY_RIGHT(elm, field) = (head)->sph_root; \
|
||||
SPLAY_LEFT((head)->sph_root, field) = NULL; \
|
||||
} else if (__comp > 0) { \
|
||||
SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
|
||||
SPLAY_LEFT(elm, field) = (head)->sph_root; \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = NULL; \
|
||||
} else \
|
||||
return ((head)->sph_root); \
|
||||
} \
|
||||
(head)->sph_root = (elm); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
struct type * \
|
||||
name##_SPLAY_REMOVE(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *__tmp; \
|
||||
if (SPLAY_EMPTY(head)) \
|
||||
return (NULL); \
|
||||
name##_SPLAY(head, elm); \
|
||||
if ((cmp)(elm, (head)->sph_root) == 0) { \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
|
||||
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
|
||||
} else { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
|
||||
name##_SPLAY(head, elm); \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
|
||||
} \
|
||||
return (elm); \
|
||||
} \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
name##_SPLAY(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type __node, *__left, *__right, *__tmp; \
|
||||
int __comp; \
|
||||
\
|
||||
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
|
||||
__left = __right = &__node; \
|
||||
\
|
||||
while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \
|
||||
if (__comp < 0) { \
|
||||
__tmp = SPLAY_LEFT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if ((cmp)(elm, __tmp) < 0){ \
|
||||
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKLEFT(head, __right, field); \
|
||||
} else if (__comp > 0) { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if ((cmp)(elm, __tmp) > 0){ \
|
||||
SPLAY_ROTATE_LEFT(head, __tmp, field); \
|
||||
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKRIGHT(head, __left, field); \
|
||||
} \
|
||||
} \
|
||||
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
|
||||
} \
|
||||
\
|
||||
/* Splay with either the minimum or the maximum element \
|
||||
* Used to find minimum or maximum element in tree. \
|
||||
*/ \
|
||||
void name##_SPLAY_MINMAX(struct name *head, int __comp) \
|
||||
{ \
|
||||
struct type __node, *__left, *__right, *__tmp; \
|
||||
\
|
||||
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
|
||||
__left = __right = &__node; \
|
||||
\
|
||||
while (1) { \
|
||||
if (__comp < 0) { \
|
||||
__tmp = SPLAY_LEFT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if (__comp < 0){ \
|
||||
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKLEFT(head, __right, field); \
|
||||
} else if (__comp > 0) { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if (__comp > 0) { \
|
||||
SPLAY_ROTATE_LEFT(head, __tmp, field); \
|
||||
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKRIGHT(head, __left, field); \
|
||||
} \
|
||||
} \
|
||||
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
|
||||
}
|
||||
|
||||
#define SPLAY_NEGINF -1
|
||||
#define SPLAY_INF 1
|
||||
|
||||
#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y)
|
||||
#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y)
|
||||
#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y)
|
||||
#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y)
|
||||
#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \
|
||||
: name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
|
||||
#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \
|
||||
: name##_SPLAY_MIN_MAX(x, SPLAY_INF))
|
||||
|
||||
#define SPLAY_FOREACH(x, name, head) \
|
||||
for ((x) = SPLAY_MIN(name, head); \
|
||||
(x) != NULL; \
|
||||
(x) = SPLAY_NEXT(name, head, x))
|
||||
|
||||
/* Macros that define a red-black tree */
|
||||
#define RB_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *rbh_root; /* root of the tree */ \
|
||||
}
|
||||
|
||||
#define RB_INITIALIZER(root) \
|
||||
{ NULL }
|
||||
|
||||
#define RB_INIT(root) do { \
|
||||
(root)->rbh_root = NULL; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define RB_BLACK 0
|
||||
#define RB_RED 1
|
||||
#define RB_PLACEHOLDER NULL
|
||||
#define RB_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *rbe_left; /* left element */ \
|
||||
struct type *rbe_right; /* right element */ \
|
||||
struct type *rbe_parent; /* parent element */ \
|
||||
}
|
||||
|
||||
#define RB_COLOR_MASK (uintptr_t)0x1
|
||||
#define RB_LEFT(elm, field) (elm)->field.rbe_left
|
||||
#define RB_RIGHT(elm, field) (elm)->field.rbe_right
|
||||
#define _RB_PARENT(elm, field) (elm)->field.rbe_parent
|
||||
#define RB_ROOT(head) (head)->rbh_root
|
||||
#define RB_EMPTY(head) (RB_ROOT(head) == NULL)
|
||||
|
||||
#define RB_SET(name, elm, parent, field) do { \
|
||||
name##_RB_SETPARENT(elm, parent); \
|
||||
RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
|
||||
name##_RB_SETCOLOR(elm, RB_RED); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define RB_SET_BLACKRED(name, black, red, field) do { \
|
||||
name##_RB_SETCOLOR(black, RB_BLACK); \
|
||||
name##_RB_SETCOLOR(red, RB_RED); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#ifndef RB_AUGMENT
|
||||
#define RB_AUGMENT(x) (void)(x)
|
||||
#endif
|
||||
|
||||
#define RB_ROTATE_LEFT(name, head, elm, tmp, field) do { \
|
||||
(tmp) = RB_RIGHT(elm, field); \
|
||||
if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \
|
||||
name##_RB_SETPARENT(RB_LEFT(tmp, field),(elm)); \
|
||||
} \
|
||||
RB_AUGMENT(elm); \
|
||||
if (name##_RB_SETPARENT(tmp, name##_RB_GETPARENT(elm)) != NULL) { \
|
||||
if ((elm) == RB_LEFT(name##_RB_GETPARENT(elm), field)) \
|
||||
RB_LEFT(name##_RB_GETPARENT(elm), field) = (tmp); \
|
||||
else \
|
||||
RB_RIGHT(name##_RB_GETPARENT(elm), field) = (tmp); \
|
||||
} else \
|
||||
(head)->rbh_root = (tmp); \
|
||||
RB_LEFT(tmp, field) = (elm); \
|
||||
name##_RB_SETPARENT(elm, (tmp)); \
|
||||
RB_AUGMENT(tmp); \
|
||||
if ((name##_RB_GETPARENT(tmp))) \
|
||||
RB_AUGMENT(name##_RB_GETPARENT(tmp)); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define RB_ROTATE_RIGHT(name, head, elm, tmp, field) do { \
|
||||
(tmp) = RB_LEFT(elm, field); \
|
||||
if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \
|
||||
name##_RB_SETPARENT(RB_RIGHT(tmp, field), (elm)); \
|
||||
} \
|
||||
RB_AUGMENT(elm); \
|
||||
if (name##_RB_SETPARENT(tmp, name##_RB_GETPARENT(elm)) != NULL) { \
|
||||
if ((elm) == RB_LEFT(name##_RB_GETPARENT(elm), field)) \
|
||||
RB_LEFT(name##_RB_GETPARENT(elm), field) = (tmp); \
|
||||
else \
|
||||
RB_RIGHT(name##_RB_GETPARENT(elm), field) = (tmp); \
|
||||
} else \
|
||||
(head)->rbh_root = (tmp); \
|
||||
RB_RIGHT(tmp, field) = (elm); \
|
||||
name##_RB_SETPARENT(elm, tmp); \
|
||||
RB_AUGMENT(tmp); \
|
||||
if ((name##_RB_GETPARENT(tmp))) \
|
||||
RB_AUGMENT(name##_RB_GETPARENT(tmp)); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
/* Generates prototypes and inline functions */
|
||||
#define RB_PROTOTYPE(name, type, field, cmp) \
|
||||
void name##_RB_INSERT_COLOR(struct name *, struct type *); \
|
||||
void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
|
||||
struct type *name##_RB_REMOVE(struct name *, struct type *); \
|
||||
struct type *name##_RB_INSERT(struct name *, struct type *); \
|
||||
struct type *name##_RB_FIND(struct name *, struct type *); \
|
||||
struct type *name##_RB_NEXT(struct type *); \
|
||||
struct type *name##_RB_MINMAX(struct name *, int); \
|
||||
struct type *name##_RB_GETPARENT(struct type*); \
|
||||
struct type *name##_RB_SETPARENT(struct type*, struct type*); \
|
||||
int name##_RB_GETCOLOR(struct type*); \
|
||||
void name##_RB_SETCOLOR(struct type*,int);
|
||||
|
||||
/* Generates prototypes (with storage class) and inline functions */
|
||||
#define RB_PROTOTYPE_SC(_sc_, name, type, field, cmp) \
|
||||
_sc_ void name##_RB_INSERT_COLOR(struct name *, struct type *); \
|
||||
_sc_ void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *); \
|
||||
_sc_ struct type *name##_RB_REMOVE(struct name *, struct type *); \
|
||||
_sc_ struct type *name##_RB_INSERT(struct name *, struct type *); \
|
||||
_sc_ struct type *name##_RB_FIND(struct name *, struct type *); \
|
||||
_sc_ struct type *name##_RB_NEXT(struct type *); \
|
||||
_sc_ struct type *name##_RB_MINMAX(struct name *, int); \
|
||||
_sc_ struct type *name##_RB_GETPARENT(struct type*); \
|
||||
_sc_ struct type *name##_RB_SETPARENT(struct type*, struct type*); \
|
||||
_sc_ int name##_RB_GETCOLOR(struct type*); \
|
||||
_sc_ void name##_RB_SETCOLOR(struct type*,int);
|
||||
|
||||
|
||||
/* Main rb operation.
|
||||
* Moves node close to the key of elm to top
|
||||
*/
|
||||
#define RB_GENERATE(name, type, field, cmp) \
|
||||
struct type *name##_RB_GETPARENT(struct type *elm) { \
|
||||
struct type *parent = _RB_PARENT(elm, field); \
|
||||
if( parent != NULL) { \
|
||||
parent = (struct type*)((uintptr_t)parent & ~RB_COLOR_MASK);\
|
||||
return( (struct type*) ( (parent == (struct type*) RB_PLACEHOLDER) ? NULL: parent));\
|
||||
} \
|
||||
return((struct type*)NULL); \
|
||||
} \
|
||||
int name##_RB_GETCOLOR(struct type *elm) { \
|
||||
int color = 0; \
|
||||
color = (int)((uintptr_t)_RB_PARENT(elm,field) & RB_COLOR_MASK);\
|
||||
return(color); \
|
||||
} \
|
||||
void name##_RB_SETCOLOR(struct type *elm,int color) { \
|
||||
struct type *parent = name##_RB_GETPARENT(elm); \
|
||||
if(parent == (struct type*)NULL) \
|
||||
parent = (struct type*) RB_PLACEHOLDER; \
|
||||
_RB_PARENT(elm, field) = (struct type*)((uintptr_t)parent | (unsigned int)color);\
|
||||
} \
|
||||
struct type *name##_RB_SETPARENT(struct type *elm, struct type *parent) { \
|
||||
int color = name##_RB_GETCOLOR(elm); \
|
||||
_RB_PARENT(elm, field) = parent; \
|
||||
if(color) name##_RB_SETCOLOR(elm, color); \
|
||||
return(name##_RB_GETPARENT(elm)); \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *parent, *gparent, *tmp; \
|
||||
while ((parent = name##_RB_GETPARENT(elm)) != NULL && \
|
||||
name##_RB_GETCOLOR(parent) == RB_RED) { \
|
||||
gparent = name##_RB_GETPARENT(parent); \
|
||||
if (parent == RB_LEFT(gparent, field)) { \
|
||||
tmp = RB_RIGHT(gparent, field); \
|
||||
if (tmp && name##_RB_GETCOLOR(tmp) == RB_RED) { \
|
||||
name##_RB_SETCOLOR(tmp, RB_BLACK); \
|
||||
RB_SET_BLACKRED(name, parent, gparent, field);\
|
||||
elm = gparent; \
|
||||
continue; \
|
||||
} \
|
||||
if (RB_RIGHT(parent, field) == elm) { \
|
||||
RB_ROTATE_LEFT(name, head, parent, tmp, field);\
|
||||
tmp = parent; \
|
||||
parent = elm; \
|
||||
elm = tmp; \
|
||||
} \
|
||||
RB_SET_BLACKRED(name, parent, gparent, field); \
|
||||
RB_ROTATE_RIGHT(name,head, gparent, tmp, field); \
|
||||
} else { \
|
||||
tmp = RB_LEFT(gparent, field); \
|
||||
if (tmp && name##_RB_GETCOLOR(tmp) == RB_RED) { \
|
||||
name##_RB_SETCOLOR(tmp, RB_BLACK); \
|
||||
RB_SET_BLACKRED(name, parent, gparent, field);\
|
||||
elm = gparent; \
|
||||
continue; \
|
||||
} \
|
||||
if (RB_LEFT(parent, field) == elm) { \
|
||||
RB_ROTATE_RIGHT(name, head, parent, tmp, field);\
|
||||
tmp = parent; \
|
||||
parent = elm; \
|
||||
elm = tmp; \
|
||||
} \
|
||||
RB_SET_BLACKRED(name, parent, gparent, field); \
|
||||
RB_ROTATE_LEFT(name, head, gparent, tmp, field); \
|
||||
} \
|
||||
} \
|
||||
name##_RB_SETCOLOR(head->rbh_root, RB_BLACK); \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp; \
|
||||
while ((elm == NULL || name##_RB_GETCOLOR(elm) == RB_BLACK) && \
|
||||
elm != RB_ROOT(head)) { \
|
||||
if (RB_LEFT(parent, field) == elm) { \
|
||||
tmp = RB_RIGHT(parent, field); \
|
||||
if (name##_RB_GETCOLOR(tmp) == RB_RED) { \
|
||||
RB_SET_BLACKRED(name, tmp, parent, field); \
|
||||
RB_ROTATE_LEFT(name, head, parent, tmp, field);\
|
||||
tmp = RB_RIGHT(parent, field); \
|
||||
} \
|
||||
if ((RB_LEFT(tmp, field) == NULL || \
|
||||
name##_RB_GETCOLOR(RB_LEFT(tmp, field)) == RB_BLACK) &&\
|
||||
(RB_RIGHT(tmp, field) == NULL || \
|
||||
name##_RB_GETCOLOR(RB_RIGHT(tmp, field)) == RB_BLACK)) {\
|
||||
name##_RB_SETCOLOR(tmp, RB_RED); \
|
||||
elm = parent; \
|
||||
parent = name##_RB_GETPARENT(elm); \
|
||||
} else { \
|
||||
if (RB_RIGHT(tmp, field) == NULL || \
|
||||
name##_RB_GETCOLOR(RB_RIGHT(tmp, field)) == RB_BLACK) {\
|
||||
struct type *oleft; \
|
||||
if ((oleft = RB_LEFT(tmp, field)) \
|
||||
!= NULL) \
|
||||
name##_RB_SETCOLOR(oleft, RB_BLACK);\
|
||||
name##_RB_SETCOLOR(tmp, RB_RED); \
|
||||
RB_ROTATE_RIGHT(name, head, tmp, oleft, field);\
|
||||
tmp = RB_RIGHT(parent, field); \
|
||||
} \
|
||||
name##_RB_SETCOLOR(tmp, (name##_RB_GETCOLOR(parent)));\
|
||||
name##_RB_SETCOLOR(parent, RB_BLACK); \
|
||||
if (RB_RIGHT(tmp, field)) \
|
||||
name##_RB_SETCOLOR(RB_RIGHT(tmp, field),RB_BLACK);\
|
||||
RB_ROTATE_LEFT(name, head, parent, tmp, field);\
|
||||
elm = RB_ROOT(head); \
|
||||
break; \
|
||||
} \
|
||||
} else { \
|
||||
tmp = RB_LEFT(parent, field); \
|
||||
if (name##_RB_GETCOLOR(tmp) == RB_RED) { \
|
||||
RB_SET_BLACKRED(name, tmp, parent, field); \
|
||||
RB_ROTATE_RIGHT(name, head, parent, tmp, field);\
|
||||
tmp = RB_LEFT(parent, field); \
|
||||
} \
|
||||
if ((RB_LEFT(tmp, field) == NULL || \
|
||||
name##_RB_GETCOLOR(RB_LEFT(tmp, field)) == RB_BLACK) &&\
|
||||
(RB_RIGHT(tmp, field) == NULL || \
|
||||
name##_RB_GETCOLOR(RB_RIGHT(tmp, field)) == RB_BLACK)) {\
|
||||
name##_RB_SETCOLOR(tmp, RB_RED); \
|
||||
elm = parent; \
|
||||
parent = name##_RB_GETPARENT(elm); \
|
||||
} else { \
|
||||
if (RB_LEFT(tmp, field) == NULL || \
|
||||
name##_RB_GETCOLOR(RB_LEFT(tmp, field)) == RB_BLACK) {\
|
||||
struct type *oright; \
|
||||
if ((oright = RB_RIGHT(tmp, field)) \
|
||||
!= NULL) \
|
||||
name##_RB_SETCOLOR(oright, RB_BLACK);\
|
||||
name##_RB_SETCOLOR(tmp, RB_RED); \
|
||||
RB_ROTATE_LEFT(name, head, tmp, oright, field);\
|
||||
tmp = RB_LEFT(parent, field); \
|
||||
} \
|
||||
name##_RB_SETCOLOR(tmp,(name##_RB_GETCOLOR(parent)));\
|
||||
name##_RB_SETCOLOR(parent, RB_BLACK); \
|
||||
if (RB_LEFT(tmp, field)) \
|
||||
name##_RB_SETCOLOR(RB_LEFT(tmp, field), RB_BLACK);\
|
||||
RB_ROTATE_RIGHT(name, head, parent, tmp, field);\
|
||||
elm = RB_ROOT(head); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
if (elm) \
|
||||
name##_RB_SETCOLOR(elm, RB_BLACK); \
|
||||
} \
|
||||
\
|
||||
struct type * \
|
||||
name##_RB_REMOVE(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *child, *parent, *old = elm; \
|
||||
int color; \
|
||||
if (RB_LEFT(elm, field) == NULL) \
|
||||
child = RB_RIGHT(elm, field); \
|
||||
else if (RB_RIGHT(elm, field) == NULL) \
|
||||
child = RB_LEFT(elm, field); \
|
||||
else { \
|
||||
struct type *left; \
|
||||
elm = RB_RIGHT(elm, field); \
|
||||
while ((left = RB_LEFT(elm, field)) != NULL) \
|
||||
elm = left; \
|
||||
child = RB_RIGHT(elm, field); \
|
||||
parent = name##_RB_GETPARENT(elm); \
|
||||
color = name##_RB_GETCOLOR(elm); \
|
||||
if (child) \
|
||||
name##_RB_SETPARENT(child, parent); \
|
||||
if (parent) { \
|
||||
if (RB_LEFT(parent, field) == elm) \
|
||||
RB_LEFT(parent, field) = child; \
|
||||
else \
|
||||
RB_RIGHT(parent, field) = child; \
|
||||
RB_AUGMENT(parent); \
|
||||
} else \
|
||||
RB_ROOT(head) = child; \
|
||||
if (name##_RB_GETPARENT(elm) == old) \
|
||||
parent = elm; \
|
||||
(elm)->field = (old)->field; \
|
||||
if (name##_RB_GETPARENT(old)) { \
|
||||
if (RB_LEFT(name##_RB_GETPARENT(old), field) == old)\
|
||||
RB_LEFT(name##_RB_GETPARENT(old), field) = elm;\
|
||||
else \
|
||||
RB_RIGHT(name##_RB_GETPARENT(old), field) = elm;\
|
||||
RB_AUGMENT(name##_RB_GETPARENT(old)); \
|
||||
} else \
|
||||
RB_ROOT(head) = elm; \
|
||||
name##_RB_SETPARENT(RB_LEFT(old, field), elm); \
|
||||
if (RB_RIGHT(old, field)) \
|
||||
name##_RB_SETPARENT(RB_RIGHT(old, field), elm); \
|
||||
if (parent) { \
|
||||
left = parent; \
|
||||
do { \
|
||||
RB_AUGMENT(left); \
|
||||
} while ((left = name##_RB_GETPARENT(left)) != NULL); \
|
||||
} \
|
||||
goto color; \
|
||||
} \
|
||||
parent = name##_RB_GETPARENT(elm); \
|
||||
color = name##_RB_GETCOLOR(elm); \
|
||||
if (child) \
|
||||
name##_RB_SETPARENT(child, parent); \
|
||||
if (parent) { \
|
||||
if (RB_LEFT(parent, field) == elm) \
|
||||
RB_LEFT(parent, field) = child; \
|
||||
else \
|
||||
RB_RIGHT(parent, field) = child; \
|
||||
RB_AUGMENT(parent); \
|
||||
} else \
|
||||
RB_ROOT(head) = child; \
|
||||
color: \
|
||||
if (color == RB_BLACK) \
|
||||
name##_RB_REMOVE_COLOR(head, parent, child); \
|
||||
return (old); \
|
||||
} \
|
||||
\
|
||||
/* Inserts a node into the RB tree */ \
|
||||
struct type * \
|
||||
name##_RB_INSERT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp; \
|
||||
struct type *parent = NULL; \
|
||||
int comp = 0; \
|
||||
tmp = RB_ROOT(head); \
|
||||
while (tmp) { \
|
||||
parent = tmp; \
|
||||
comp = (cmp)(elm, parent); \
|
||||
if (comp < 0) \
|
||||
tmp = RB_LEFT(tmp, field); \
|
||||
else if (comp > 0) \
|
||||
tmp = RB_RIGHT(tmp, field); \
|
||||
else \
|
||||
return (tmp); \
|
||||
} \
|
||||
RB_SET(name, elm, parent, field); \
|
||||
if (parent != NULL) { \
|
||||
if (comp < 0) \
|
||||
RB_LEFT(parent, field) = elm; \
|
||||
else \
|
||||
RB_RIGHT(parent, field) = elm; \
|
||||
RB_AUGMENT(parent); \
|
||||
} else \
|
||||
RB_ROOT(head) = elm; \
|
||||
name##_RB_INSERT_COLOR(head, elm); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
/* Finds the node with the same key as elm */ \
|
||||
struct type * \
|
||||
name##_RB_FIND(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp = RB_ROOT(head); \
|
||||
int comp; \
|
||||
while (tmp) { \
|
||||
comp = cmp(elm, tmp); \
|
||||
if (comp < 0) \
|
||||
tmp = RB_LEFT(tmp, field); \
|
||||
else if (comp > 0) \
|
||||
tmp = RB_RIGHT(tmp, field); \
|
||||
else \
|
||||
return (tmp); \
|
||||
} \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
/* ARGSUSED */ \
|
||||
struct type * \
|
||||
name##_RB_NEXT(struct type *elm) \
|
||||
{ \
|
||||
if (RB_RIGHT(elm, field)) { \
|
||||
elm = RB_RIGHT(elm, field); \
|
||||
while (RB_LEFT(elm, field)) \
|
||||
elm = RB_LEFT(elm, field); \
|
||||
} else { \
|
||||
if (name##_RB_GETPARENT(elm) && \
|
||||
(elm == RB_LEFT(name##_RB_GETPARENT(elm), field))) \
|
||||
elm = name##_RB_GETPARENT(elm); \
|
||||
else { \
|
||||
while (name##_RB_GETPARENT(elm) && \
|
||||
(elm == RB_RIGHT(name##_RB_GETPARENT(elm), field)))\
|
||||
elm = name##_RB_GETPARENT(elm); \
|
||||
elm = name##_RB_GETPARENT(elm); \
|
||||
} \
|
||||
} \
|
||||
return (elm); \
|
||||
} \
|
||||
\
|
||||
struct type * \
|
||||
name##_RB_MINMAX(struct name *head, int val) \
|
||||
{ \
|
||||
struct type *tmp = RB_ROOT(head); \
|
||||
struct type *parent = NULL; \
|
||||
while (tmp) { \
|
||||
parent = tmp; \
|
||||
if (val < 0) \
|
||||
tmp = RB_LEFT(tmp, field); \
|
||||
else \
|
||||
tmp = RB_RIGHT(tmp, field); \
|
||||
} \
|
||||
return (parent); \
|
||||
}
|
||||
|
||||
|
||||
#define RB_PROTOTYPE_PREV(name, type, field, cmp) \
|
||||
RB_PROTOTYPE(name, type, field, cmp) \
|
||||
struct type *name##_RB_PREV(struct type *);
|
||||
|
||||
|
||||
#define RB_PROTOTYPE_SC_PREV(_sc_, name, type, field, cmp) \
|
||||
RB_PROTOTYPE_SC(_sc_, name, type, field, cmp) \
|
||||
_sc_ struct type *name##_RB_PREV(struct type *);
|
||||
|
||||
#define RB_GENERATE_PREV(name, type, field, cmp) \
|
||||
RB_GENERATE(name, type, field, cmp) \
|
||||
struct type * \
|
||||
name##_RB_PREV(struct type *elm) \
|
||||
{ \
|
||||
if (RB_LEFT(elm, field)) { \
|
||||
elm = RB_LEFT(elm, field); \
|
||||
while (RB_RIGHT(elm, field)) \
|
||||
elm = RB_RIGHT(elm, field); \
|
||||
} else { \
|
||||
if (name##_RB_GETPARENT(elm) && \
|
||||
(elm == RB_RIGHT(name##_RB_GETPARENT(elm), field))) \
|
||||
elm = name##_RB_GETPARENT(elm); \
|
||||
else { \
|
||||
while (name##_RB_GETPARENT(elm) && \
|
||||
(elm == RB_LEFT(name##_RB_GETPARENT(elm), field)))\
|
||||
elm = name##_RB_GETPARENT(elm); \
|
||||
elm = name##_RB_GETPARENT(elm); \
|
||||
} \
|
||||
} \
|
||||
return (elm); \
|
||||
} \
|
||||
|
||||
#define RB_NEGINF -1
|
||||
#define RB_INF 1
|
||||
|
||||
#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
|
||||
#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
|
||||
#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
|
||||
#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
|
||||
#define RB_PREV(name, x, y) name##_RB_PREV(y)
|
||||
#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
|
||||
#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
|
||||
|
||||
#define RB_FOREACH(x, name, head) \
|
||||
for ((x) = RB_MIN(name, head); \
|
||||
(x) != NULL; \
|
||||
(x) = name##_RB_NEXT(x))
|
||||
|
||||
#define RB_FOREACH_FROM(x, name, y) \
|
||||
for ((x) = (y); \
|
||||
((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
|
||||
(x) = (y))
|
||||
|
||||
#define RB_FOREACH_REVERSE_FROM(x, name, y) \
|
||||
for ((x) = (y); \
|
||||
((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
|
||||
(x) = (y))
|
||||
|
||||
#define RB_FOREACH_SAFE(x, name, head, y) \
|
||||
for ((x) = RB_MIN(name, head); \
|
||||
((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
|
||||
(x) = (y))
|
||||
|
||||
#endif /* _LIBKERN_TREE_H_ */
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2008 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. The rights granted to you under the License
|
||||
* may not be used to create, or enable the creation or redistribution of,
|
||||
* unlawful or unlicensed copies of an Apple operating system, or to
|
||||
* circumvent, violate, or enable the circumvention or violation of, any
|
||||
* terms of an Apple operating system software license agreement.
|
||||
*
|
||||
* Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)radix.h 8.2 (Berkeley) 10/31/94
|
||||
* $FreeBSD: src/sys/net/radix.h,v 1.16.2.1 2000/05/03 19:17:11 wollman Exp $
|
||||
*/
|
||||
|
||||
#ifndef _RADIX_H_
|
||||
#define _RADIX_H_
|
||||
#include <sys/appleapiopts.h>
|
||||
|
||||
#ifdef PRIVATE
|
||||
|
||||
#ifdef MALLOC_DECLARE
|
||||
MALLOC_DECLARE(M_RTABLE);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Radix search tree node layout.
|
||||
*/
|
||||
|
||||
struct radix_node {
|
||||
struct radix_mask *rn_mklist; /* list of masks contained in subtree */
|
||||
struct radix_node *rn_parent; /* parent */
|
||||
short rn_bit; /* bit offset; -1-index(netmask) */
|
||||
char rn_bmask; /* node: mask for bit test*/
|
||||
u_char rn_flags; /* enumerated next */
|
||||
#define RNF_NORMAL 1 /* leaf contains normal route */
|
||||
#define RNF_ROOT 2 /* leaf is root leaf for tree */
|
||||
#define RNF_ACTIVE 4 /* This node is alive (for rtfree) */
|
||||
union {
|
||||
struct { /* leaf only data: */
|
||||
caddr_t rn_Key; /* object of search */
|
||||
caddr_t rn_Mask; /* netmask, if present */
|
||||
struct radix_node *rn_Dupedkey;
|
||||
} rn_leaf;
|
||||
struct { /* node only data: */
|
||||
int rn_Off; /* where to start compare */
|
||||
struct radix_node *rn_L;/* progeny */
|
||||
struct radix_node *rn_R;/* progeny */
|
||||
} rn_node;
|
||||
} rn_u;
|
||||
#ifdef RN_DEBUG
|
||||
int rn_info;
|
||||
struct radix_node *rn_twin;
|
||||
struct radix_node *rn_ybro;
|
||||
#endif
|
||||
|
||||
#if __arm__ && (__BIGGEST_ALIGNMENT__ > 4)
|
||||
/* For the newer ARMv7k ABI where 64-bit types are 64-bit aligned, but pointers
|
||||
* are 32-bit:
|
||||
* Aligned to 64-bit since this is cast to rtentry, which is 64-bit aligned.
|
||||
*/
|
||||
} __attribute__ ((aligned(8)));
|
||||
#else
|
||||
};
|
||||
#endif
|
||||
|
||||
#define rn_dupedkey rn_u.rn_leaf.rn_Dupedkey
|
||||
#define rn_key rn_u.rn_leaf.rn_Key
|
||||
#define rn_mask rn_u.rn_leaf.rn_Mask
|
||||
#define rn_offset rn_u.rn_node.rn_Off
|
||||
#define rn_left rn_u.rn_node.rn_L
|
||||
#define rn_right rn_u.rn_node.rn_R
|
||||
|
||||
/*
|
||||
* Annotations to tree concerning potential routes applying to subtrees.
|
||||
*/
|
||||
|
||||
struct radix_mask {
|
||||
short rm_bit; /* bit offset; -1-index(netmask) */
|
||||
char rm_unused; /* cf. rn_bmask */
|
||||
u_char rm_flags; /* cf. rn_flags */
|
||||
struct radix_mask *rm_mklist; /* more masks to try */
|
||||
union {
|
||||
caddr_t rmu_mask; /* the mask */
|
||||
struct radix_node *rmu_leaf; /* for normal routes */
|
||||
} rm_rmu;
|
||||
int rm_refs; /* # of references to this struct */
|
||||
};
|
||||
|
||||
#define rm_mask rm_rmu.rmu_mask
|
||||
#define rm_leaf rm_rmu.rmu_leaf /* extra field would make 32 bytes */
|
||||
|
||||
|
||||
#define MKGet(m) {\
|
||||
if (rn_mkfreelist) {\
|
||||
m = rn_mkfreelist; \
|
||||
rn_mkfreelist = (m)->rm_mklist; \
|
||||
} else \
|
||||
R_Malloc(m, struct radix_mask *, sizeof (*(m))); }\
|
||||
|
||||
#define MKFree(m) { (m)->rm_mklist = rn_mkfreelist; rn_mkfreelist = (m);}
|
||||
|
||||
typedef int walktree_f_t(struct radix_node *, void *);
|
||||
typedef int rn_matchf_t(struct radix_node *, void *);
|
||||
|
||||
struct radix_node_head {
|
||||
struct radix_node *rnh_treetop;
|
||||
int rnh_addrsize; /* permit, but not require fixed keys */
|
||||
int rnh_pktsize; /* permit, but not require fixed keys */
|
||||
struct radix_node *(*rnh_addaddr) /* add based on sockaddr */
|
||||
(void *v, void *mask,
|
||||
struct radix_node_head *head, struct radix_node nodes[]);
|
||||
struct radix_node *(*rnh_addpkt) /* add based on packet hdr */
|
||||
(void *v, void *mask,
|
||||
struct radix_node_head *head, struct radix_node nodes[]);
|
||||
struct radix_node *(*rnh_deladdr) /* remove based on sockaddr */
|
||||
(void *v, void *mask, struct radix_node_head *head);
|
||||
struct radix_node *(*rnh_delpkt) /* remove based on packet hdr */
|
||||
(void *v, void *mask, struct radix_node_head *head);
|
||||
struct radix_node *(*rnh_matchaddr) /* locate based on sockaddr */
|
||||
(void *v, struct radix_node_head *head);
|
||||
/* locate based on sockaddr and rn_matchf_t() */
|
||||
struct radix_node *(*rnh_matchaddr_args)
|
||||
(void *v, struct radix_node_head *head,
|
||||
rn_matchf_t *f, void *w);
|
||||
struct radix_node *(*rnh_lookup) /* locate based on sockaddr */
|
||||
(void *v, void *mask, struct radix_node_head *head);
|
||||
/* locate based on sockaddr, mask and rn_matchf_t() */
|
||||
struct radix_node *(*rnh_lookup_args)
|
||||
(void *v, void *mask, struct radix_node_head *head,
|
||||
rn_matchf_t *f, void *);
|
||||
struct radix_node *(*rnh_matchpkt) /* locate based on packet hdr */
|
||||
(void *v, struct radix_node_head *head);
|
||||
int (*rnh_walktree) /* traverse tree */
|
||||
(struct radix_node_head *head, walktree_f_t *f, void *w);
|
||||
int (*rnh_walktree_from) /* traverse tree below a */
|
||||
(struct radix_node_head *head, void *a, void *m,
|
||||
walktree_f_t *f, void *w);
|
||||
void (*rnh_close) /* do something when the last ref drops */
|
||||
(struct radix_node *rn, struct radix_node_head *head);
|
||||
struct radix_node rnh_nodes[3]; /* empty tree for common case */
|
||||
int rnh_cnt; /* tree dimension */
|
||||
};
|
||||
|
||||
#ifndef KERNEL
|
||||
#define Bcmp(a, b, n) bcmp(((char *)(a)), ((char *)(b)), (n))
|
||||
#define Bcopy(a, b, n) bcopy(((char *)(a)), ((char *)(b)), (unsigned)(n))
|
||||
#define Bzero(p, n) bzero((char *)(p), (int)(n));
|
||||
#define R_Malloc(p, t, n) (p = (t) malloc((unsigned int)(n)))
|
||||
#define R_Free(p) free((char *)p);
|
||||
#else
|
||||
#define Bcmp(a, b, n) bcmp(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n))
|
||||
#define Bcopy(a, b, n) bcopy(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n))
|
||||
#define Bzero(p, n) bzero((caddr_t)(p), (unsigned)(n));
|
||||
#define R_Malloc(p, t, n) (p = (t) _MALLOC((uint32_t)(n), M_RTABLE, M_WAITOK))
|
||||
#define R_Free(p) FREE((caddr_t)p, M_RTABLE);
|
||||
#endif /*KERNEL*/
|
||||
|
||||
void rn_init(void);
|
||||
int rn_inithead(void **, int);
|
||||
int rn_refines(void *, void *);
|
||||
struct radix_node
|
||||
*rn_addmask(void *, int, int),
|
||||
*rn_addroute(void *, void *, struct radix_node_head *,
|
||||
struct radix_node [2]),
|
||||
*rn_delete(void *, void *, struct radix_node_head *),
|
||||
*rn_lookup(void *v_arg, void *m_arg, struct radix_node_head *head),
|
||||
*rn_lookup_args(void *v_arg, void *m_arg, struct radix_node_head *head,
|
||||
rn_matchf_t *, void *),
|
||||
*rn_match(void *, struct radix_node_head *),
|
||||
*rn_match_args(void *, struct radix_node_head *, rn_matchf_t *, void *);
|
||||
|
||||
#endif /* PRIVATE */
|
||||
#endif /* _RADIX_H_ */
|
@ -0,0 +1,367 @@
|
||||
APPLE PUBLIC SOURCE LICENSE
|
||||
Version 2.0 - August 6, 2003
|
||||
|
||||
Please read this License carefully before downloading this software.
|
||||
By downloading or using this software, you are agreeing to be bound by
|
||||
the terms of this License. If you do not or cannot agree to the terms
|
||||
of this License, please do not download or use the software.
|
||||
|
||||
1. General; Definitions. This License applies to any program or other
|
||||
work which Apple Computer, Inc. ("Apple") makes publicly available and
|
||||
which contains a notice placed by Apple identifying such program or
|
||||
work as "Original Code" and stating that it is subject to the terms of
|
||||
this Apple Public Source License version 2.0 ("License"). As used in
|
||||
this License:
|
||||
|
||||
1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is
|
||||
the grantor of rights, (i) claims of patents that are now or hereafter
|
||||
acquired, owned by or assigned to Apple and (ii) that cover subject
|
||||
matter contained in the Original Code, but only to the extent
|
||||
necessary to use, reproduce and/or distribute the Original Code
|
||||
without infringement; and (b) in the case where You are the grantor of
|
||||
rights, (i) claims of patents that are now or hereafter acquired,
|
||||
owned by or assigned to You and (ii) that cover subject matter in Your
|
||||
Modifications, taken alone or in combination with Original Code.
|
||||
|
||||
1.2 "Contributor" means any person or entity that creates or
|
||||
contributes to the creation of Modifications.
|
||||
|
||||
1.3 "Covered Code" means the Original Code, Modifications, the
|
||||
combination of Original Code and any Modifications, and/or any
|
||||
respective portions thereof.
|
||||
|
||||
1.4 "Externally Deploy" means: (a) to sublicense, distribute or
|
||||
otherwise make Covered Code available, directly or indirectly, to
|
||||
anyone other than You; and/or (b) to use Covered Code, alone or as
|
||||
part of a Larger Work, in any way to provide a service, including but
|
||||
not limited to delivery of content, through electronic communication
|
||||
with a client other than You.
|
||||
|
||||
1.5 "Larger Work" means a work which combines Covered Code or portions
|
||||
thereof with code not governed by the terms of this License.
|
||||
|
||||
1.6 "Modifications" mean any addition to, deletion from, and/or change
|
||||
to, the substance and/or structure of the Original Code, any previous
|
||||
Modifications, the combination of Original Code and any previous
|
||||
Modifications, and/or any respective portions thereof. When code is
|
||||
released as a series of files, a Modification is: (a) any addition to
|
||||
or deletion from the contents of a file containing Covered Code;
|
||||
and/or (b) any new file or other representation of computer program
|
||||
statements that contains any part of Covered Code.
|
||||
|
||||
1.7 "Original Code" means (a) the Source Code of a program or other
|
||||
work as originally made available by Apple under this License,
|
||||
including the Source Code of any updates or upgrades to such programs
|
||||
or works made available by Apple under this License, and that has been
|
||||
expressly identified by Apple as such in the header file(s) of such
|
||||
work; and (b) the object code compiled from such Source Code and
|
||||
originally made available by Apple under this License.
|
||||
|
||||
1.8 "Source Code" means the human readable form of a program or other
|
||||
work that is suitable for making modifications to it, including all
|
||||
modules it contains, plus any associated interface definition files,
|
||||
scripts used to control compilation and installation of an executable
|
||||
(object code).
|
||||
|
||||
1.9 "You" or "Your" means an individual or a legal entity exercising
|
||||
rights under this License. For legal entities, "You" or "Your"
|
||||
includes any entity which controls, is controlled by, or is under
|
||||
common control with, You, where "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of fifty percent
|
||||
(50%) or more of the outstanding shares or beneficial ownership of
|
||||
such entity.
|
||||
|
||||
2. Permitted Uses; Conditions & Restrictions. Subject to the terms
|
||||
and conditions of this License, Apple hereby grants You, effective on
|
||||
the date You accept this License and download the Original Code, a
|
||||
world-wide, royalty-free, non-exclusive license, to the extent of
|
||||
Apple's Applicable Patent Rights and copyrights covering the Original
|
||||
Code, to do the following:
|
||||
|
||||
2.1 Unmodified Code. You may use, reproduce, display, perform,
|
||||
internally distribute within Your organization, and Externally Deploy
|
||||
verbatim, unmodified copies of the Original Code, for commercial or
|
||||
non-commercial purposes, provided that in each instance:
|
||||
|
||||
(a) You must retain and reproduce in all copies of Original Code the
|
||||
copyright and other proprietary notices and disclaimers of Apple as
|
||||
they appear in the Original Code, and keep intact all notices in the
|
||||
Original Code that refer to this License; and
|
||||
|
||||
(b) You must include a copy of this License with every copy of Source
|
||||
Code of Covered Code and documentation You distribute or Externally
|
||||
Deploy, and You may not offer or impose any terms on such Source Code
|
||||
that alter or restrict this License or the recipients' rights
|
||||
hereunder, except as permitted under Section 6.
|
||||
|
||||
2.2 Modified Code. You may modify Covered Code and use, reproduce,
|
||||
display, perform, internally distribute within Your organization, and
|
||||
Externally Deploy Your Modifications and Covered Code, for commercial
|
||||
or non-commercial purposes, provided that in each instance You also
|
||||
meet all of these conditions:
|
||||
|
||||
(a) You must satisfy all the conditions of Section 2.1 with respect to
|
||||
the Source Code of the Covered Code;
|
||||
|
||||
(b) You must duplicate, to the extent it does not already exist, the
|
||||
notice in Exhibit A in each file of the Source Code of all Your
|
||||
Modifications, and cause the modified files to carry prominent notices
|
||||
stating that You changed the files and the date of any change; and
|
||||
|
||||
(c) If You Externally Deploy Your Modifications, You must make
|
||||
Source Code of all Your Externally Deployed Modifications either
|
||||
available to those to whom You have Externally Deployed Your
|
||||
Modifications, or publicly available. Source Code of Your Externally
|
||||
Deployed Modifications must be released under the terms set forth in
|
||||
this License, including the license grants set forth in Section 3
|
||||
below, for as long as you Externally Deploy the Covered Code or twelve
|
||||
(12) months from the date of initial External Deployment, whichever is
|
||||
longer. You should preferably distribute the Source Code of Your
|
||||
Externally Deployed Modifications electronically (e.g. download from a
|
||||
web site).
|
||||
|
||||
2.3 Distribution of Executable Versions. In addition, if You
|
||||
Externally Deploy Covered Code (Original Code and/or Modifications) in
|
||||
object code, executable form only, You must include a prominent
|
||||
notice, in the code itself as well as in related documentation,
|
||||
stating that Source Code of the Covered Code is available under the
|
||||
terms of this License with information on how and where to obtain such
|
||||
Source Code.
|
||||
|
||||
2.4 Third Party Rights. You expressly acknowledge and agree that
|
||||
although Apple and each Contributor grants the licenses to their
|
||||
respective portions of the Covered Code set forth herein, no
|
||||
assurances are provided by Apple or any Contributor that the Covered
|
||||
Code does not infringe the patent or other intellectual property
|
||||
rights of any other entity. Apple and each Contributor disclaim any
|
||||
liability to You for claims brought by any other entity based on
|
||||
infringement of intellectual property rights or otherwise. As a
|
||||
condition to exercising the rights and licenses granted hereunder, You
|
||||
hereby assume sole responsibility to secure any other intellectual
|
||||
property rights needed, if any. For example, if a third party patent
|
||||
license is required to allow You to distribute the Covered Code, it is
|
||||
Your responsibility to acquire that license before distributing the
|
||||
Covered Code.
|
||||
|
||||
3. Your Grants. In consideration of, and as a condition to, the
|
||||
licenses granted to You under this License, You hereby grant to any
|
||||
person or entity receiving or distributing Covered Code under this
|
||||
License a non-exclusive, royalty-free, perpetual, irrevocable license,
|
||||
under Your Applicable Patent Rights and other intellectual property
|
||||
rights (other than patent) owned or controlled by You, to use,
|
||||
reproduce, display, perform, modify, sublicense, distribute and
|
||||
Externally Deploy Your Modifications of the same scope and extent as
|
||||
Apple's licenses under Sections 2.1 and 2.2 above.
|
||||
|
||||
4. Larger Works. You may create a Larger Work by combining Covered
|
||||
Code with other code not governed by the terms of this License and
|
||||
distribute the Larger Work as a single product. In each such instance,
|
||||
You must make sure the requirements of this License are fulfilled for
|
||||
the Covered Code or any portion thereof.
|
||||
|
||||
5. Limitations on Patent License. Except as expressly stated in
|
||||
Section 2, no other patent rights, express or implied, are granted by
|
||||
Apple herein. Modifications and/or Larger Works may require additional
|
||||
patent licenses from Apple which Apple may grant in its sole
|
||||
discretion.
|
||||
|
||||
6. Additional Terms. You may choose to offer, and to charge a fee for,
|
||||
warranty, support, indemnity or liability obligations and/or other
|
||||
rights consistent with the scope of the license granted herein
|
||||
("Additional Terms") to one or more recipients of Covered Code.
|
||||
However, You may do so only on Your own behalf and as Your sole
|
||||
responsibility, and not on behalf of Apple or any Contributor. You
|
||||
must obtain the recipient's agreement that any such Additional Terms
|
||||
are offered by You alone, and You hereby agree to indemnify, defend
|
||||
and hold Apple and every Contributor harmless for any liability
|
||||
incurred by or claims asserted against Apple or such Contributor by
|
||||
reason of any such Additional Terms.
|
||||
|
||||
7. Versions of the License. Apple may publish revised and/or new
|
||||
versions of this License from time to time. Each version will be given
|
||||
a distinguishing version number. Once Original Code has been published
|
||||
under a particular version of this License, You may continue to use it
|
||||
under the terms of that version. You may also choose to use such
|
||||
Original Code under the terms of any subsequent version of this
|
||||
License published by Apple. No one other than Apple has the right to
|
||||
modify the terms applicable to Covered Code created under this
|
||||
License.
|
||||
|
||||
8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in
|
||||
part pre-release, untested, or not fully tested works. The Covered
|
||||
Code may contain errors that could cause failures or loss of data, and
|
||||
may be incomplete or contain inaccuracies. You expressly acknowledge
|
||||
and agree that use of the Covered Code, or any portion thereof, is at
|
||||
Your sole and entire risk. THE COVERED CODE IS PROVIDED "AS IS" AND
|
||||
WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND AND APPLE AND
|
||||
APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE
|
||||
PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM
|
||||
ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT
|
||||
NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF
|
||||
MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR
|
||||
PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD
|
||||
PARTY RIGHTS. APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST
|
||||
INTERFERENCE WITH YOUR ENJOYMENT OF THE COVERED CODE, THAT THE
|
||||
FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR REQUIREMENTS,
|
||||
THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR
|
||||
ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO
|
||||
ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE
|
||||
AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY.
|
||||
You acknowledge that the Covered Code is not intended for use in the
|
||||
operation of nuclear facilities, aircraft navigation, communication
|
||||
systems, or air traffic control machines in which case the failure of
|
||||
the Covered Code could lead to death, personal injury, or severe
|
||||
physical or environmental damage.
|
||||
|
||||
9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO
|
||||
EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL,
|
||||
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING
|
||||
TO THIS LICENSE OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR
|
||||
ANY PORTION THEREOF, WHETHER UNDER A THEORY OF CONTRACT, WARRANTY,
|
||||
TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF
|
||||
APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY
|
||||
REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF
|
||||
INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY
|
||||
TO YOU. In no event shall Apple's total liability to You for all
|
||||
damages (other than as may be required by applicable law) under this
|
||||
License exceed the amount of fifty dollars ($50.00).
|
||||
|
||||
10. Trademarks. This License does not grant any rights to use the
|
||||
trademarks or trade names "Apple", "Apple Computer", "Mac", "Mac OS",
|
||||
"QuickTime", "QuickTime Streaming Server" or any other trademarks,
|
||||
service marks, logos or trade names belonging to Apple (collectively
|
||||
"Apple Marks") or to any trademark, service mark, logo or trade name
|
||||
belonging to any Contributor. You agree not to use any Apple Marks in
|
||||
or as part of the name of products derived from the Original Code or
|
||||
to endorse or promote products derived from the Original Code other
|
||||
than as expressly permitted by and in strict compliance at all times
|
||||
with Apple's third party trademark usage guidelines which are posted
|
||||
at http://www.apple.com/legal/guidelinesfor3rdparties.html.
|
||||
|
||||
11. Ownership. Subject to the licenses granted under this License,
|
||||
each Contributor retains all rights, title and interest in and to any
|
||||
Modifications made by such Contributor. Apple retains all rights,
|
||||
title and interest in and to the Original Code and any Modifications
|
||||
made by or on behalf of Apple ("Apple Modifications"), and such Apple
|
||||
Modifications will not be automatically subject to this License. Apple
|
||||
may, at its sole discretion, choose to license such Apple
|
||||
Modifications under this License, or on different terms from those
|
||||
contained in this License or may choose not to license them at all.
|
||||
|
||||
12. Termination.
|
||||
|
||||
12.1 Termination. This License and the rights granted hereunder will
|
||||
terminate:
|
||||
|
||||
(a) automatically without notice from Apple if You fail to comply with
|
||||
any term(s) of this License and fail to cure such breach within 30
|
||||
days of becoming aware of such breach;
|
||||
|
||||
(b) immediately in the event of the circumstances described in Section
|
||||
13.5(b); or
|
||||
|
||||
(c) automatically without notice from Apple if You, at any time during
|
||||
the term of this License, commence an action for patent infringement
|
||||
against Apple; provided that Apple did not first commence
|
||||
an action for patent infringement against You in that instance.
|
||||
|
||||
12.2 Effect of Termination. Upon termination, You agree to immediately
|
||||
stop any further use, reproduction, modification, sublicensing and
|
||||
distribution of the Covered Code. All sublicenses to the Covered Code
|
||||
which have been properly granted prior to termination shall survive
|
||||
any termination of this License. Provisions which, by their nature,
|
||||
should remain in effect beyond the termination of this License shall
|
||||
survive, including but not limited to Sections 3, 5, 8, 9, 10, 11,
|
||||
12.2 and 13. No party will be liable to any other for compensation,
|
||||
indemnity or damages of any sort solely as a result of terminating
|
||||
this License in accordance with its terms, and termination of this
|
||||
License will be without prejudice to any other right or remedy of
|
||||
any party.
|
||||
|
||||
13. Miscellaneous.
|
||||
|
||||
13.1 Government End Users. The Covered Code is a "commercial item" as
|
||||
defined in FAR 2.101. Government software and technical data rights in
|
||||
the Covered Code include only those rights customarily provided to the
|
||||
public as defined in this License. This customary commercial license
|
||||
in technical data and software is provided in accordance with FAR
|
||||
12.211 (Technical Data) and 12.212 (Computer Software) and, for
|
||||
Department of Defense purchases, DFAR 252.227-7015 (Technical Data --
|
||||
Commercial Items) and 227.7202-3 (Rights in Commercial Computer
|
||||
Software or Computer Software Documentation). Accordingly, all U.S.
|
||||
Government End Users acquire Covered Code with only those rights set
|
||||
forth herein.
|
||||
|
||||
13.2 Relationship of Parties. This License will not be construed as
|
||||
creating an agency, partnership, joint venture or any other form of
|
||||
legal association between or among You, Apple or any Contributor, and
|
||||
You will not represent to the contrary, whether expressly, by
|
||||
implication, appearance or otherwise.
|
||||
|
||||
13.3 Independent Development. Nothing in this License will impair
|
||||
Apple's right to acquire, license, develop, have others develop for
|
||||
it, market and/or distribute technology or products that perform the
|
||||
same or similar functions as, or otherwise compete with,
|
||||
Modifications, Larger Works, technology or products that You may
|
||||
develop, produce, market or distribute.
|
||||
|
||||
13.4 Waiver; Construction. Failure by Apple or any Contributor to
|
||||
enforce any provision of this License will not be deemed a waiver of
|
||||
future enforcement of that or any other provision. Any law or
|
||||
regulation which provides that the language of a contract shall be
|
||||
construed against the drafter will not apply to this License.
|
||||
|
||||
13.5 Severability. (a) If for any reason a court of competent
|
||||
jurisdiction finds any provision of this License, or portion thereof,
|
||||
to be unenforceable, that provision of the License will be enforced to
|
||||
the maximum extent permissible so as to effect the economic benefits
|
||||
and intent of the parties, and the remainder of this License will
|
||||
continue in full force and effect. (b) Notwithstanding the foregoing,
|
||||
if applicable law prohibits or restricts You from fully and/or
|
||||
specifically complying with Sections 2 and/or 3 or prevents the
|
||||
enforceability of either of those Sections, this License will
|
||||
immediately terminate and You must immediately discontinue any use of
|
||||
the Covered Code and destroy all copies of it that are in your
|
||||
possession or control.
|
||||
|
||||
13.6 Dispute Resolution. Any litigation or other dispute resolution
|
||||
between You and Apple relating to this License shall take place in the
|
||||
Northern District of California, and You and Apple hereby consent to
|
||||
the personal jurisdiction of, and venue in, the state and federal
|
||||
courts within that District with respect to this License. The
|
||||
application of the United Nations Convention on Contracts for the
|
||||
International Sale of Goods is expressly excluded.
|
||||
|
||||
13.7 Entire Agreement; Governing Law. This License constitutes the
|
||||
entire agreement between the parties with respect to the subject
|
||||
matter hereof. This License shall be governed by the laws of the
|
||||
United States and the State of California, except that body of
|
||||
California law concerning conflicts of law.
|
||||
|
||||
Where You are located in the province of Quebec, Canada, the following
|
||||
clause applies: The parties hereby confirm that they have requested
|
||||
that this License and all related documents be drafted in English. Les
|
||||
parties ont exige que le present contrat et tous les documents
|
||||
connexes soient rediges en anglais.
|
||||
|
||||
EXHIBIT A.
|
||||
|
||||
"Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
|
||||
Reserved.
|
||||
|
||||
This file contains Original Code and/or Modifications of Original Code
|
||||
as defined in and that are subject to the Apple Public Source License
|
||||
Version 2.0 (the 'License'). You may not use this file except in
|
||||
compliance with the License. Please obtain a copy of the License at
|
||||
http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
file.
|
||||
|
||||
The Original Code and all software distributed under the License are
|
||||
distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
Please see the License for the specific language governing rights and
|
||||
limitations under the License."
|
@ -0,0 +1,802 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2010 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. The rights granted to you under the License
|
||||
* may not be used to create, or enable the creation or redistribution of,
|
||||
* unlawful or unlicensed copies of an Apple operating system, or to
|
||||
* circumvent, violate, or enable the circumvention or violation of, any
|
||||
* terms of an Apple operating system software license agreement.
|
||||
*
|
||||
* Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
/* $NetBSD: tree.h,v 1.13 2006/08/27 22:32:38 christos Exp $ */
|
||||
/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */
|
||||
/*
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _LIBKERN_TREE_H_
|
||||
#define _LIBKERN_TREE_H_
|
||||
|
||||
/*
|
||||
* This file defines data structures for different types of trees:
|
||||
* splay trees and red-black trees.
|
||||
*
|
||||
* A splay tree is a self-organizing data structure. Every operation
|
||||
* on the tree causes a splay to happen. The splay moves the requested
|
||||
* node to the root of the tree and partly rebalances it.
|
||||
*
|
||||
* This has the benefit that request locality causes faster lookups as
|
||||
* the requested nodes move to the top of the tree. On the other hand,
|
||||
* every lookup causes memory writes.
|
||||
*
|
||||
* The Balance Theorem bounds the total access time for m operations
|
||||
* and n inserts on an initially empty tree as O((m + n)lg n). The
|
||||
* amortized cost for a sequence of m accesses to a splay tree is O(lg n);
|
||||
*
|
||||
* A red-black tree is a binary search tree with the node color as an
|
||||
* extra attribute. It fulfills a set of conditions:
|
||||
* - every search path from the root to a leaf consists of the
|
||||
* same number of black nodes,
|
||||
* - each red node (except for the root) has a black parent,
|
||||
* - each leaf node is black.
|
||||
*
|
||||
* Every operation on a red-black tree is bounded as O(lg n).
|
||||
* The maximum height of a red-black tree is 2lg (n+1).
|
||||
*/
|
||||
|
||||
#define SPLAY_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *sph_root; /* root of the tree */ \
|
||||
}
|
||||
|
||||
#define SPLAY_INITIALIZER(root) \
|
||||
{ NULL }
|
||||
|
||||
#define SPLAY_INIT(root) do { \
|
||||
(root)->sph_root = NULL; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *spe_left; /* left element */ \
|
||||
struct type *spe_right; /* right element */ \
|
||||
}
|
||||
|
||||
#define SPLAY_LEFT(elm, field) (elm)->field.spe_left
|
||||
#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right
|
||||
#define SPLAY_ROOT(head) (head)->sph_root
|
||||
#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL)
|
||||
|
||||
/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
|
||||
#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \
|
||||
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
|
||||
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
|
||||
(head)->sph_root = tmp; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
|
||||
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
|
||||
(head)->sph_root = tmp; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_LINKLEFT(head, tmp, field) do { \
|
||||
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
|
||||
tmp = (head)->sph_root; \
|
||||
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_LINKRIGHT(head, tmp, field) do { \
|
||||
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
|
||||
tmp = (head)->sph_root; \
|
||||
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
|
||||
SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
|
||||
SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
|
||||
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
/* Generates prototypes and inline functions */
|
||||
|
||||
#define SPLAY_PROTOTYPE(name, type, field, cmp) \
|
||||
void name##_SPLAY(struct name *, struct type *); \
|
||||
void name##_SPLAY_MINMAX(struct name *, int); \
|
||||
struct type *name##_SPLAY_INSERT(struct name *, struct type *); \
|
||||
struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \
|
||||
\
|
||||
/* Finds the node with the same key as elm */ \
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_FIND(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
if (SPLAY_EMPTY(head)) \
|
||||
return(NULL); \
|
||||
name##_SPLAY(head, elm); \
|
||||
if ((cmp)(elm, (head)->sph_root) == 0) \
|
||||
return (head->sph_root); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_NEXT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
name##_SPLAY(head, elm); \
|
||||
if (SPLAY_RIGHT(elm, field) != NULL) { \
|
||||
elm = SPLAY_RIGHT(elm, field); \
|
||||
while (SPLAY_LEFT(elm, field) != NULL) { \
|
||||
elm = SPLAY_LEFT(elm, field); \
|
||||
} \
|
||||
} else \
|
||||
elm = NULL; \
|
||||
return (elm); \
|
||||
} \
|
||||
\
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_MIN_MAX(struct name *head, int val) \
|
||||
{ \
|
||||
name##_SPLAY_MINMAX(head, val); \
|
||||
return (SPLAY_ROOT(head)); \
|
||||
}
|
||||
|
||||
/* Main splay operation.
|
||||
* Moves node close to the key of elm to top
|
||||
*/
|
||||
#define SPLAY_GENERATE(name, type, field, cmp) \
|
||||
struct type * \
|
||||
name##_SPLAY_INSERT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
if (SPLAY_EMPTY(head)) { \
|
||||
SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \
|
||||
} else { \
|
||||
int __comp; \
|
||||
name##_SPLAY(head, elm); \
|
||||
__comp = (cmp)(elm, (head)->sph_root); \
|
||||
if(__comp < 0) { \
|
||||
SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
|
||||
SPLAY_RIGHT(elm, field) = (head)->sph_root; \
|
||||
SPLAY_LEFT((head)->sph_root, field) = NULL; \
|
||||
} else if (__comp > 0) { \
|
||||
SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
|
||||
SPLAY_LEFT(elm, field) = (head)->sph_root; \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = NULL; \
|
||||
} else \
|
||||
return ((head)->sph_root); \
|
||||
} \
|
||||
(head)->sph_root = (elm); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
struct type * \
|
||||
name##_SPLAY_REMOVE(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *__tmp; \
|
||||
if (SPLAY_EMPTY(head)) \
|
||||
return (NULL); \
|
||||
name##_SPLAY(head, elm); \
|
||||
if ((cmp)(elm, (head)->sph_root) == 0) { \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
|
||||
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
|
||||
} else { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
|
||||
name##_SPLAY(head, elm); \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
|
||||
} \
|
||||
return (elm); \
|
||||
} \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
name##_SPLAY(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type __node, *__left, *__right, *__tmp; \
|
||||
int __comp; \
|
||||
\
|
||||
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
|
||||
__left = __right = &__node; \
|
||||
\
|
||||
while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \
|
||||
if (__comp < 0) { \
|
||||
__tmp = SPLAY_LEFT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if ((cmp)(elm, __tmp) < 0){ \
|
||||
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKLEFT(head, __right, field); \
|
||||
} else if (__comp > 0) { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if ((cmp)(elm, __tmp) > 0){ \
|
||||
SPLAY_ROTATE_LEFT(head, __tmp, field); \
|
||||
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKRIGHT(head, __left, field); \
|
||||
} \
|
||||
} \
|
||||
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
|
||||
} \
|
||||
\
|
||||
/* Splay with either the minimum or the maximum element \
|
||||
* Used to find minimum or maximum element in tree. \
|
||||
*/ \
|
||||
void name##_SPLAY_MINMAX(struct name *head, int __comp) \
|
||||
{ \
|
||||
struct type __node, *__left, *__right, *__tmp; \
|
||||
\
|
||||
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
|
||||
__left = __right = &__node; \
|
||||
\
|
||||
while (1) { \
|
||||
if (__comp < 0) { \
|
||||
__tmp = SPLAY_LEFT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if (__comp < 0){ \
|
||||
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKLEFT(head, __right, field); \
|
||||
} else if (__comp > 0) { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if (__comp > 0) { \
|
||||
SPLAY_ROTATE_LEFT(head, __tmp, field); \
|
||||
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKRIGHT(head, __left, field); \
|
||||
} \
|
||||
} \
|
||||
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
|
||||
}
|
||||
|
||||
#define SPLAY_NEGINF -1
|
||||
#define SPLAY_INF 1
|
||||
|
||||
#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y)
|
||||
#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y)
|
||||
#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y)
|
||||
#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y)
|
||||
#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \
|
||||
: name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
|
||||
#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \
|
||||
: name##_SPLAY_MIN_MAX(x, SPLAY_INF))
|
||||
|
||||
#define SPLAY_FOREACH(x, name, head) \
|
||||
for ((x) = SPLAY_MIN(name, head); \
|
||||
(x) != NULL; \
|
||||
(x) = SPLAY_NEXT(name, head, x))
|
||||
|
||||
/* Macros that define a red-black tree */
|
||||
#define RB_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *rbh_root; /* root of the tree */ \
|
||||
}
|
||||
|
||||
#define RB_INITIALIZER(root) \
|
||||
{ NULL }
|
||||
|
||||
#define RB_INIT(root) do { \
|
||||
(root)->rbh_root = NULL; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define RB_BLACK 0
|
||||
#define RB_RED 1
|
||||
#define RB_PLACEHOLDER NULL
|
||||
#define RB_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *rbe_left; /* left element */ \
|
||||
struct type *rbe_right; /* right element */ \
|
||||
struct type *rbe_parent; /* parent element */ \
|
||||
}
|
||||
|
||||
#define RB_COLOR_MASK (uintptr_t)0x1
|
||||
#define RB_LEFT(elm, field) (elm)->field.rbe_left
|
||||
#define RB_RIGHT(elm, field) (elm)->field.rbe_right
|
||||
#define _RB_PARENT(elm, field) (elm)->field.rbe_parent
|
||||
#define RB_ROOT(head) (head)->rbh_root
|
||||
#define RB_EMPTY(head) (RB_ROOT(head) == NULL)
|
||||
|
||||
#define RB_SET(name, elm, parent, field) do { \
|
||||
name##_RB_SETPARENT(elm, parent); \
|
||||
RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
|
||||
name##_RB_SETCOLOR(elm, RB_RED); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define RB_SET_BLACKRED(name, black, red, field) do { \
|
||||
name##_RB_SETCOLOR(black, RB_BLACK); \
|
||||
name##_RB_SETCOLOR(red, RB_RED); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#ifndef RB_AUGMENT
|
||||
#define RB_AUGMENT(x) (void)(x)
|
||||
#endif
|
||||
|
||||
#define RB_ROTATE_LEFT(name, head, elm, tmp, field) do { \
|
||||
(tmp) = RB_RIGHT(elm, field); \
|
||||
if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \
|
||||
name##_RB_SETPARENT(RB_LEFT(tmp, field),(elm)); \
|
||||
} \
|
||||
RB_AUGMENT(elm); \
|
||||
if (name##_RB_SETPARENT(tmp, name##_RB_GETPARENT(elm)) != NULL) { \
|
||||
if ((elm) == RB_LEFT(name##_RB_GETPARENT(elm), field)) \
|
||||
RB_LEFT(name##_RB_GETPARENT(elm), field) = (tmp); \
|
||||
else \
|
||||
RB_RIGHT(name##_RB_GETPARENT(elm), field) = (tmp); \
|
||||
} else \
|
||||
(head)->rbh_root = (tmp); \
|
||||
RB_LEFT(tmp, field) = (elm); \
|
||||
name##_RB_SETPARENT(elm, (tmp)); \
|
||||
RB_AUGMENT(tmp); \
|
||||
if ((name##_RB_GETPARENT(tmp))) \
|
||||
RB_AUGMENT(name##_RB_GETPARENT(tmp)); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define RB_ROTATE_RIGHT(name, head, elm, tmp, field) do { \
|
||||
(tmp) = RB_LEFT(elm, field); \
|
||||
if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \
|
||||
name##_RB_SETPARENT(RB_RIGHT(tmp, field), (elm)); \
|
||||
} \
|
||||
RB_AUGMENT(elm); \
|
||||
if (name##_RB_SETPARENT(tmp, name##_RB_GETPARENT(elm)) != NULL) { \
|
||||
if ((elm) == RB_LEFT(name##_RB_GETPARENT(elm), field)) \
|
||||
RB_LEFT(name##_RB_GETPARENT(elm), field) = (tmp); \
|
||||
else \
|
||||
RB_RIGHT(name##_RB_GETPARENT(elm), field) = (tmp); \
|
||||
} else \
|
||||
(head)->rbh_root = (tmp); \
|
||||
RB_RIGHT(tmp, field) = (elm); \
|
||||
name##_RB_SETPARENT(elm, tmp); \
|
||||
RB_AUGMENT(tmp); \
|
||||
if ((name##_RB_GETPARENT(tmp))) \
|
||||
RB_AUGMENT(name##_RB_GETPARENT(tmp)); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
/* Generates prototypes and inline functions */
|
||||
#define RB_PROTOTYPE(name, type, field, cmp) \
|
||||
void name##_RB_INSERT_COLOR(struct name *, struct type *); \
|
||||
void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
|
||||
struct type *name##_RB_REMOVE(struct name *, struct type *); \
|
||||
struct type *name##_RB_INSERT(struct name *, struct type *); \
|
||||
struct type *name##_RB_FIND(struct name *, struct type *); \
|
||||
struct type *name##_RB_NEXT(struct type *); \
|
||||
struct type *name##_RB_MINMAX(struct name *, int); \
|
||||
struct type *name##_RB_GETPARENT(struct type*); \
|
||||
struct type *name##_RB_SETPARENT(struct type*, struct type*); \
|
||||
int name##_RB_GETCOLOR(struct type*); \
|
||||
void name##_RB_SETCOLOR(struct type*,int);
|
||||
|
||||
/* Generates prototypes (with storage class) and inline functions */
|
||||
#define RB_PROTOTYPE_SC(_sc_, name, type, field, cmp) \
|
||||
_sc_ void name##_RB_INSERT_COLOR(struct name *, struct type *); \
|
||||
_sc_ void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *); \
|
||||
_sc_ struct type *name##_RB_REMOVE(struct name *, struct type *); \
|
||||
_sc_ struct type *name##_RB_INSERT(struct name *, struct type *); \
|
||||
_sc_ struct type *name##_RB_FIND(struct name *, struct type *); \
|
||||
_sc_ struct type *name##_RB_NEXT(struct type *); \
|
||||
_sc_ struct type *name##_RB_MINMAX(struct name *, int); \
|
||||
_sc_ struct type *name##_RB_GETPARENT(struct type*); \
|
||||
_sc_ struct type *name##_RB_SETPARENT(struct type*, struct type*); \
|
||||
_sc_ int name##_RB_GETCOLOR(struct type*); \
|
||||
_sc_ void name##_RB_SETCOLOR(struct type*,int);
|
||||
|
||||
|
||||
/* Main rb operation.
|
||||
* Moves node close to the key of elm to top
|
||||
*/
|
||||
#define RB_GENERATE(name, type, field, cmp) \
|
||||
struct type *name##_RB_GETPARENT(struct type *elm) { \
|
||||
struct type *parent = _RB_PARENT(elm, field); \
|
||||
if( parent != NULL) { \
|
||||
parent = (struct type*)((uintptr_t)parent & ~RB_COLOR_MASK);\
|
||||
return( (struct type*) ( (parent == (struct type*) RB_PLACEHOLDER) ? NULL: parent));\
|
||||
} \
|
||||
return((struct type*)NULL); \
|
||||
} \
|
||||
int name##_RB_GETCOLOR(struct type *elm) { \
|
||||
int color = 0; \
|
||||
color = (int)((uintptr_t)_RB_PARENT(elm,field) & RB_COLOR_MASK);\
|
||||
return(color); \
|
||||
} \
|
||||
void name##_RB_SETCOLOR(struct type *elm,int color) { \
|
||||
struct type *parent = name##_RB_GETPARENT(elm); \
|
||||
if(parent == (struct type*)NULL) \
|
||||
parent = (struct type*) RB_PLACEHOLDER; \
|
||||
_RB_PARENT(elm, field) = (struct type*)((uintptr_t)parent | (unsigned int)color);\
|
||||
} \
|
||||
struct type *name##_RB_SETPARENT(struct type *elm, struct type *parent) { \
|
||||
int color = name##_RB_GETCOLOR(elm); \
|
||||
_RB_PARENT(elm, field) = parent; \
|
||||
if(color) name##_RB_SETCOLOR(elm, color); \
|
||||
return(name##_RB_GETPARENT(elm)); \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *parent, *gparent, *tmp; \
|
||||
while ((parent = name##_RB_GETPARENT(elm)) != NULL && \
|
||||
name##_RB_GETCOLOR(parent) == RB_RED) { \
|
||||
gparent = name##_RB_GETPARENT(parent); \
|
||||
if (parent == RB_LEFT(gparent, field)) { \
|
||||
tmp = RB_RIGHT(gparent, field); \
|
||||
if (tmp && name##_RB_GETCOLOR(tmp) == RB_RED) { \
|
||||
name##_RB_SETCOLOR(tmp, RB_BLACK); \
|
||||
RB_SET_BLACKRED(name, parent, gparent, field);\
|
||||
elm = gparent; \
|
||||
continue; \
|
||||
} \
|
||||
if (RB_RIGHT(parent, field) == elm) { \
|
||||
RB_ROTATE_LEFT(name, head, parent, tmp, field);\
|
||||
tmp = parent; \
|
||||
parent = elm; \
|
||||
elm = tmp; \
|
||||
} \
|
||||
RB_SET_BLACKRED(name, parent, gparent, field); \
|
||||
RB_ROTATE_RIGHT(name,head, gparent, tmp, field); \
|
||||
} else { \
|
||||
tmp = RB_LEFT(gparent, field); \
|
||||
if (tmp && name##_RB_GETCOLOR(tmp) == RB_RED) { \
|
||||
name##_RB_SETCOLOR(tmp, RB_BLACK); \
|
||||
RB_SET_BLACKRED(name, parent, gparent, field);\
|
||||
elm = gparent; \
|
||||
continue; \
|
||||
} \
|
||||
if (RB_LEFT(parent, field) == elm) { \
|
||||
RB_ROTATE_RIGHT(name, head, parent, tmp, field);\
|
||||
tmp = parent; \
|
||||
parent = elm; \
|
||||
elm = tmp; \
|
||||
} \
|
||||
RB_SET_BLACKRED(name, parent, gparent, field); \
|
||||
RB_ROTATE_LEFT(name, head, gparent, tmp, field); \
|
||||
} \
|
||||
} \
|
||||
name##_RB_SETCOLOR(head->rbh_root, RB_BLACK); \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp; \
|
||||
while ((elm == NULL || name##_RB_GETCOLOR(elm) == RB_BLACK) && \
|
||||
elm != RB_ROOT(head)) { \
|
||||
if (RB_LEFT(parent, field) == elm) { \
|
||||
tmp = RB_RIGHT(parent, field); \
|
||||
if (name##_RB_GETCOLOR(tmp) == RB_RED) { \
|
||||
RB_SET_BLACKRED(name, tmp, parent, field); \
|
||||
RB_ROTATE_LEFT(name, head, parent, tmp, field);\
|
||||
tmp = RB_RIGHT(parent, field); \
|
||||
} \
|
||||
if ((RB_LEFT(tmp, field) == NULL || \
|
||||
name##_RB_GETCOLOR(RB_LEFT(tmp, field)) == RB_BLACK) &&\
|
||||
(RB_RIGHT(tmp, field) == NULL || \
|
||||
name##_RB_GETCOLOR(RB_RIGHT(tmp, field)) == RB_BLACK)) {\
|
||||
name##_RB_SETCOLOR(tmp, RB_RED); \
|
||||
elm = parent; \
|
||||
parent = name##_RB_GETPARENT(elm); \
|
||||
} else { \
|
||||
if (RB_RIGHT(tmp, field) == NULL || \
|
||||
name##_RB_GETCOLOR(RB_RIGHT(tmp, field)) == RB_BLACK) {\
|
||||
struct type *oleft; \
|
||||
if ((oleft = RB_LEFT(tmp, field)) \
|
||||
!= NULL) \
|
||||
name##_RB_SETCOLOR(oleft, RB_BLACK);\
|
||||
name##_RB_SETCOLOR(tmp, RB_RED); \
|
||||
RB_ROTATE_RIGHT(name, head, tmp, oleft, field);\
|
||||
tmp = RB_RIGHT(parent, field); \
|
||||
} \
|
||||
name##_RB_SETCOLOR(tmp, (name##_RB_GETCOLOR(parent)));\
|
||||
name##_RB_SETCOLOR(parent, RB_BLACK); \
|
||||
if (RB_RIGHT(tmp, field)) \
|
||||
name##_RB_SETCOLOR(RB_RIGHT(tmp, field),RB_BLACK);\
|
||||
RB_ROTATE_LEFT(name, head, parent, tmp, field);\
|
||||
elm = RB_ROOT(head); \
|
||||
break; \
|
||||
} \
|
||||
} else { \
|
||||
tmp = RB_LEFT(parent, field); \
|
||||
if (name##_RB_GETCOLOR(tmp) == RB_RED) { \
|
||||
RB_SET_BLACKRED(name, tmp, parent, field); \
|
||||
RB_ROTATE_RIGHT(name, head, parent, tmp, field);\
|
||||
tmp = RB_LEFT(parent, field); \
|
||||
} \
|
||||
if ((RB_LEFT(tmp, field) == NULL || \
|
||||
name##_RB_GETCOLOR(RB_LEFT(tmp, field)) == RB_BLACK) &&\
|
||||
(RB_RIGHT(tmp, field) == NULL || \
|
||||
name##_RB_GETCOLOR(RB_RIGHT(tmp, field)) == RB_BLACK)) {\
|
||||
name##_RB_SETCOLOR(tmp, RB_RED); \
|
||||
elm = parent; \
|
||||
parent = name##_RB_GETPARENT(elm); \
|
||||
} else { \
|
||||
if (RB_LEFT(tmp, field) == NULL || \
|
||||
name##_RB_GETCOLOR(RB_LEFT(tmp, field)) == RB_BLACK) {\
|
||||
struct type *oright; \
|
||||
if ((oright = RB_RIGHT(tmp, field)) \
|
||||
!= NULL) \
|
||||
name##_RB_SETCOLOR(oright, RB_BLACK);\
|
||||
name##_RB_SETCOLOR(tmp, RB_RED); \
|
||||
RB_ROTATE_LEFT(name, head, tmp, oright, field);\
|
||||
tmp = RB_LEFT(parent, field); \
|
||||
} \
|
||||
name##_RB_SETCOLOR(tmp,(name##_RB_GETCOLOR(parent)));\
|
||||
name##_RB_SETCOLOR(parent, RB_BLACK); \
|
||||
if (RB_LEFT(tmp, field)) \
|
||||
name##_RB_SETCOLOR(RB_LEFT(tmp, field), RB_BLACK);\
|
||||
RB_ROTATE_RIGHT(name, head, parent, tmp, field);\
|
||||
elm = RB_ROOT(head); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
if (elm) \
|
||||
name##_RB_SETCOLOR(elm, RB_BLACK); \
|
||||
} \
|
||||
\
|
||||
struct type * \
|
||||
name##_RB_REMOVE(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *child, *parent, *old = elm; \
|
||||
int color; \
|
||||
if (RB_LEFT(elm, field) == NULL) \
|
||||
child = RB_RIGHT(elm, field); \
|
||||
else if (RB_RIGHT(elm, field) == NULL) \
|
||||
child = RB_LEFT(elm, field); \
|
||||
else { \
|
||||
struct type *left; \
|
||||
elm = RB_RIGHT(elm, field); \
|
||||
while ((left = RB_LEFT(elm, field)) != NULL) \
|
||||
elm = left; \
|
||||
child = RB_RIGHT(elm, field); \
|
||||
parent = name##_RB_GETPARENT(elm); \
|
||||
color = name##_RB_GETCOLOR(elm); \
|
||||
if (child) \
|
||||
name##_RB_SETPARENT(child, parent); \
|
||||
if (parent) { \
|
||||
if (RB_LEFT(parent, field) == elm) \
|
||||
RB_LEFT(parent, field) = child; \
|
||||
else \
|
||||
RB_RIGHT(parent, field) = child; \
|
||||
RB_AUGMENT(parent); \
|
||||
} else \
|
||||
RB_ROOT(head) = child; \
|
||||
if (name##_RB_GETPARENT(elm) == old) \
|
||||
parent = elm; \
|
||||
(elm)->field = (old)->field; \
|
||||
if (name##_RB_GETPARENT(old)) { \
|
||||
if (RB_LEFT(name##_RB_GETPARENT(old), field) == old)\
|
||||
RB_LEFT(name##_RB_GETPARENT(old), field) = elm;\
|
||||
else \
|
||||
RB_RIGHT(name##_RB_GETPARENT(old), field) = elm;\
|
||||
RB_AUGMENT(name##_RB_GETPARENT(old)); \
|
||||
} else \
|
||||
RB_ROOT(head) = elm; \
|
||||
name##_RB_SETPARENT(RB_LEFT(old, field), elm); \
|
||||
if (RB_RIGHT(old, field)) \
|
||||
name##_RB_SETPARENT(RB_RIGHT(old, field), elm); \
|
||||
if (parent) { \
|
||||
left = parent; \
|
||||
do { \
|
||||
RB_AUGMENT(left); \
|
||||
} while ((left = name##_RB_GETPARENT(left)) != NULL); \
|
||||
} \
|
||||
goto color; \
|
||||
} \
|
||||
parent = name##_RB_GETPARENT(elm); \
|
||||
color = name##_RB_GETCOLOR(elm); \
|
||||
if (child) \
|
||||
name##_RB_SETPARENT(child, parent); \
|
||||
if (parent) { \
|
||||
if (RB_LEFT(parent, field) == elm) \
|
||||
RB_LEFT(parent, field) = child; \
|
||||
else \
|
||||
RB_RIGHT(parent, field) = child; \
|
||||
RB_AUGMENT(parent); \
|
||||
} else \
|
||||
RB_ROOT(head) = child; \
|
||||
color: \
|
||||
if (color == RB_BLACK) \
|
||||
name##_RB_REMOVE_COLOR(head, parent, child); \
|
||||
return (old); \
|
||||
} \
|
||||
\
|
||||
/* Inserts a node into the RB tree */ \
|
||||
struct type * \
|
||||
name##_RB_INSERT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp; \
|
||||
struct type *parent = NULL; \
|
||||
int comp = 0; \
|
||||
tmp = RB_ROOT(head); \
|
||||
while (tmp) { \
|
||||
parent = tmp; \
|
||||
comp = (cmp)(elm, parent); \
|
||||
if (comp < 0) \
|
||||
tmp = RB_LEFT(tmp, field); \
|
||||
else if (comp > 0) \
|
||||
tmp = RB_RIGHT(tmp, field); \
|
||||
else \
|
||||
return (tmp); \
|
||||
} \
|
||||
RB_SET(name, elm, parent, field); \
|
||||
if (parent != NULL) { \
|
||||
if (comp < 0) \
|
||||
RB_LEFT(parent, field) = elm; \
|
||||
else \
|
||||
RB_RIGHT(parent, field) = elm; \
|
||||
RB_AUGMENT(parent); \
|
||||
} else \
|
||||
RB_ROOT(head) = elm; \
|
||||
name##_RB_INSERT_COLOR(head, elm); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
/* Finds the node with the same key as elm */ \
|
||||
struct type * \
|
||||
name##_RB_FIND(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp = RB_ROOT(head); \
|
||||
int comp; \
|
||||
while (tmp) { \
|
||||
comp = cmp(elm, tmp); \
|
||||
if (comp < 0) \
|
||||
tmp = RB_LEFT(tmp, field); \
|
||||
else if (comp > 0) \
|
||||
tmp = RB_RIGHT(tmp, field); \
|
||||
else \
|
||||
return (tmp); \
|
||||
} \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
/* ARGSUSED */ \
|
||||
struct type * \
|
||||
name##_RB_NEXT(struct type *elm) \
|
||||
{ \
|
||||
if (RB_RIGHT(elm, field)) { \
|
||||
elm = RB_RIGHT(elm, field); \
|
||||
while (RB_LEFT(elm, field)) \
|
||||
elm = RB_LEFT(elm, field); \
|
||||
} else { \
|
||||
if (name##_RB_GETPARENT(elm) && \
|
||||
(elm == RB_LEFT(name##_RB_GETPARENT(elm), field))) \
|
||||
elm = name##_RB_GETPARENT(elm); \
|
||||
else { \
|
||||
while (name##_RB_GETPARENT(elm) && \
|
||||
(elm == RB_RIGHT(name##_RB_GETPARENT(elm), field)))\
|
||||
elm = name##_RB_GETPARENT(elm); \
|
||||
elm = name##_RB_GETPARENT(elm); \
|
||||
} \
|
||||
} \
|
||||
return (elm); \
|
||||
} \
|
||||
\
|
||||
struct type * \
|
||||
name##_RB_MINMAX(struct name *head, int val) \
|
||||
{ \
|
||||
struct type *tmp = RB_ROOT(head); \
|
||||
struct type *parent = NULL; \
|
||||
while (tmp) { \
|
||||
parent = tmp; \
|
||||
if (val < 0) \
|
||||
tmp = RB_LEFT(tmp, field); \
|
||||
else \
|
||||
tmp = RB_RIGHT(tmp, field); \
|
||||
} \
|
||||
return (parent); \
|
||||
}
|
||||
|
||||
|
||||
#define RB_PROTOTYPE_PREV(name, type, field, cmp) \
|
||||
RB_PROTOTYPE(name, type, field, cmp) \
|
||||
struct type *name##_RB_PREV(struct type *);
|
||||
|
||||
|
||||
#define RB_PROTOTYPE_SC_PREV(_sc_, name, type, field, cmp) \
|
||||
RB_PROTOTYPE_SC(_sc_, name, type, field, cmp) \
|
||||
_sc_ struct type *name##_RB_PREV(struct type *);
|
||||
|
||||
#define RB_GENERATE_PREV(name, type, field, cmp) \
|
||||
RB_GENERATE(name, type, field, cmp) \
|
||||
struct type * \
|
||||
name##_RB_PREV(struct type *elm) \
|
||||
{ \
|
||||
if (RB_LEFT(elm, field)) { \
|
||||
elm = RB_LEFT(elm, field); \
|
||||
while (RB_RIGHT(elm, field)) \
|
||||
elm = RB_RIGHT(elm, field); \
|
||||
} else { \
|
||||
if (name##_RB_GETPARENT(elm) && \
|
||||
(elm == RB_RIGHT(name##_RB_GETPARENT(elm), field))) \
|
||||
elm = name##_RB_GETPARENT(elm); \
|
||||
else { \
|
||||
while (name##_RB_GETPARENT(elm) && \
|
||||
(elm == RB_LEFT(name##_RB_GETPARENT(elm), field)))\
|
||||
elm = name##_RB_GETPARENT(elm); \
|
||||
elm = name##_RB_GETPARENT(elm); \
|
||||
} \
|
||||
} \
|
||||
return (elm); \
|
||||
} \
|
||||
|
||||
#define RB_NEGINF -1
|
||||
#define RB_INF 1
|
||||
|
||||
#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
|
||||
#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
|
||||
#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
|
||||
#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
|
||||
#define RB_PREV(name, x, y) name##_RB_PREV(y)
|
||||
#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
|
||||
#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
|
||||
|
||||
#define RB_FOREACH(x, name, head) \
|
||||
for ((x) = RB_MIN(name, head); \
|
||||
(x) != NULL; \
|
||||
(x) = name##_RB_NEXT(x))
|
||||
|
||||
#define RB_FOREACH_FROM(x, name, y) \
|
||||
for ((x) = (y); \
|
||||
((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
|
||||
(x) = (y))
|
||||
|
||||
#define RB_FOREACH_REVERSE_FROM(x, name, y) \
|
||||
for ((x) = (y); \
|
||||
((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
|
||||
(x) = (y))
|
||||
|
||||
#define RB_FOREACH_SAFE(x, name, head, y) \
|
||||
for ((x) = RB_MIN(name, head); \
|
||||
((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
|
||||
(x) = (y))
|
||||
|
||||
#endif /* _LIBKERN_TREE_H_ */
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2008 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. The rights granted to you under the License
|
||||
* may not be used to create, or enable the creation or redistribution of,
|
||||
* unlawful or unlicensed copies of an Apple operating system, or to
|
||||
* circumvent, violate, or enable the circumvention or violation of, any
|
||||
* terms of an Apple operating system software license agreement.
|
||||
*
|
||||
* Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)radix.h 8.2 (Berkeley) 10/31/94
|
||||
* $FreeBSD: src/sys/net/radix.h,v 1.16.2.1 2000/05/03 19:17:11 wollman Exp $
|
||||
*/
|
||||
|
||||
#ifndef _RADIX_H_
|
||||
#define _RADIX_H_
|
||||
#include <sys/appleapiopts.h>
|
||||
|
||||
#ifdef PRIVATE
|
||||
|
||||
#ifdef MALLOC_DECLARE
|
||||
MALLOC_DECLARE(M_RTABLE);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Radix search tree node layout.
|
||||
*/
|
||||
|
||||
struct radix_node {
|
||||
struct radix_mask *rn_mklist; /* list of masks contained in subtree */
|
||||
struct radix_node *rn_parent; /* parent */
|
||||
short rn_bit; /* bit offset; -1-index(netmask) */
|
||||
char rn_bmask; /* node: mask for bit test*/
|
||||
u_char rn_flags; /* enumerated next */
|
||||
#define RNF_NORMAL 1 /* leaf contains normal route */
|
||||
#define RNF_ROOT 2 /* leaf is root leaf for tree */
|
||||
#define RNF_ACTIVE 4 /* This node is alive (for rtfree) */
|
||||
union {
|
||||
struct { /* leaf only data: */
|
||||
caddr_t rn_Key; /* object of search */
|
||||
caddr_t rn_Mask; /* netmask, if present */
|
||||
struct radix_node *rn_Dupedkey;
|
||||
} rn_leaf;
|
||||
struct { /* node only data: */
|
||||
int rn_Off; /* where to start compare */
|
||||
struct radix_node *rn_L;/* progeny */
|
||||
struct radix_node *rn_R;/* progeny */
|
||||
} rn_node;
|
||||
} rn_u;
|
||||
#ifdef RN_DEBUG
|
||||
int rn_info;
|
||||
struct radix_node *rn_twin;
|
||||
struct radix_node *rn_ybro;
|
||||
#endif
|
||||
|
||||
#if __arm__ && (__BIGGEST_ALIGNMENT__ > 4)
|
||||
/* For the newer ARMv7k ABI where 64-bit types are 64-bit aligned, but pointers
|
||||
* are 32-bit:
|
||||
* Aligned to 64-bit since this is cast to rtentry, which is 64-bit aligned.
|
||||
*/
|
||||
} __attribute__ ((aligned(8)));
|
||||
#else
|
||||
};
|
||||
#endif
|
||||
|
||||
#define rn_dupedkey rn_u.rn_leaf.rn_Dupedkey
|
||||
#define rn_key rn_u.rn_leaf.rn_Key
|
||||
#define rn_mask rn_u.rn_leaf.rn_Mask
|
||||
#define rn_offset rn_u.rn_node.rn_Off
|
||||
#define rn_left rn_u.rn_node.rn_L
|
||||
#define rn_right rn_u.rn_node.rn_R
|
||||
|
||||
/*
|
||||
* Annotations to tree concerning potential routes applying to subtrees.
|
||||
*/
|
||||
|
||||
struct radix_mask {
|
||||
short rm_bit; /* bit offset; -1-index(netmask) */
|
||||
char rm_unused; /* cf. rn_bmask */
|
||||
u_char rm_flags; /* cf. rn_flags */
|
||||
struct radix_mask *rm_mklist; /* more masks to try */
|
||||
union {
|
||||
caddr_t rmu_mask; /* the mask */
|
||||
struct radix_node *rmu_leaf; /* for normal routes */
|
||||
} rm_rmu;
|
||||
int rm_refs; /* # of references to this struct */
|
||||
};
|
||||
|
||||
#define rm_mask rm_rmu.rmu_mask
|
||||
#define rm_leaf rm_rmu.rmu_leaf /* extra field would make 32 bytes */
|
||||
|
||||
|
||||
#define MKGet(m) {\
|
||||
if (rn_mkfreelist) {\
|
||||
m = rn_mkfreelist; \
|
||||
rn_mkfreelist = (m)->rm_mklist; \
|
||||
} else \
|
||||
R_Malloc(m, struct radix_mask *, sizeof (*(m))); }\
|
||||
|
||||
#define MKFree(m) { (m)->rm_mklist = rn_mkfreelist; rn_mkfreelist = (m);}
|
||||
|
||||
typedef int walktree_f_t(struct radix_node *, void *);
|
||||
typedef int rn_matchf_t(struct radix_node *, void *);
|
||||
|
||||
struct radix_node_head {
|
||||
struct radix_node *rnh_treetop;
|
||||
int rnh_addrsize; /* permit, but not require fixed keys */
|
||||
int rnh_pktsize; /* permit, but not require fixed keys */
|
||||
struct radix_node *(*rnh_addaddr) /* add based on sockaddr */
|
||||
(void *v, void *mask,
|
||||
struct radix_node_head *head, struct radix_node nodes[]);
|
||||
struct radix_node *(*rnh_addpkt) /* add based on packet hdr */
|
||||
(void *v, void *mask,
|
||||
struct radix_node_head *head, struct radix_node nodes[]);
|
||||
struct radix_node *(*rnh_deladdr) /* remove based on sockaddr */
|
||||
(void *v, void *mask, struct radix_node_head *head);
|
||||
struct radix_node *(*rnh_delpkt) /* remove based on packet hdr */
|
||||
(void *v, void *mask, struct radix_node_head *head);
|
||||
struct radix_node *(*rnh_matchaddr) /* locate based on sockaddr */
|
||||
(void *v, struct radix_node_head *head);
|
||||
/* locate based on sockaddr and rn_matchf_t() */
|
||||
struct radix_node *(*rnh_matchaddr_args)
|
||||
(void *v, struct radix_node_head *head,
|
||||
rn_matchf_t *f, void *w);
|
||||
struct radix_node *(*rnh_lookup) /* locate based on sockaddr */
|
||||
(void *v, void *mask, struct radix_node_head *head);
|
||||
/* locate based on sockaddr, mask and rn_matchf_t() */
|
||||
struct radix_node *(*rnh_lookup_args)
|
||||
(void *v, void *mask, struct radix_node_head *head,
|
||||
rn_matchf_t *f, void *);
|
||||
struct radix_node *(*rnh_matchpkt) /* locate based on packet hdr */
|
||||
(void *v, struct radix_node_head *head);
|
||||
int (*rnh_walktree) /* traverse tree */
|
||||
(struct radix_node_head *head, walktree_f_t *f, void *w);
|
||||
int (*rnh_walktree_from) /* traverse tree below a */
|
||||
(struct radix_node_head *head, void *a, void *m,
|
||||
walktree_f_t *f, void *w);
|
||||
void (*rnh_close) /* do something when the last ref drops */
|
||||
(struct radix_node *rn, struct radix_node_head *head);
|
||||
struct radix_node rnh_nodes[3]; /* empty tree for common case */
|
||||
int rnh_cnt; /* tree dimension */
|
||||
};
|
||||
|
||||
#ifndef KERNEL
|
||||
#define Bcmp(a, b, n) bcmp(((char *)(a)), ((char *)(b)), (n))
|
||||
#define Bcopy(a, b, n) bcopy(((char *)(a)), ((char *)(b)), (unsigned)(n))
|
||||
#define Bzero(p, n) bzero((char *)(p), (int)(n));
|
||||
#define R_Malloc(p, t, n) (p = (t) malloc((unsigned int)(n)))
|
||||
#define R_Free(p) free((char *)p);
|
||||
#else
|
||||
#define Bcmp(a, b, n) bcmp(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n))
|
||||
#define Bcopy(a, b, n) bcopy(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n))
|
||||
#define Bzero(p, n) bzero((caddr_t)(p), (unsigned)(n));
|
||||
#define R_Malloc(p, t, n) (p = (t) _MALLOC((uint32_t)(n), M_RTABLE, M_WAITOK))
|
||||
#define R_Free(p) FREE((caddr_t)p, M_RTABLE);
|
||||
#endif /*KERNEL*/
|
||||
|
||||
void rn_init(void);
|
||||
int rn_inithead(void **, int);
|
||||
int rn_refines(void *, void *);
|
||||
struct radix_node
|
||||
*rn_addmask(void *, int, int),
|
||||
*rn_addroute(void *, void *, struct radix_node_head *,
|
||||
struct radix_node [2]),
|
||||
*rn_delete(void *, void *, struct radix_node_head *),
|
||||
*rn_lookup(void *v_arg, void *m_arg, struct radix_node_head *head),
|
||||
*rn_lookup_args(void *v_arg, void *m_arg, struct radix_node_head *head,
|
||||
rn_matchf_t *, void *),
|
||||
*rn_match(void *, struct radix_node_head *),
|
||||
*rn_match_args(void *, struct radix_node_head *, rn_matchf_t *, void *);
|
||||
|
||||
#endif /* PRIVATE */
|
||||
#endif /* _RADIX_H_ */
|
@ -0,0 +1,367 @@
|
||||
APPLE PUBLIC SOURCE LICENSE
|
||||
Version 2.0 - August 6, 2003
|
||||
|
||||
Please read this License carefully before downloading this software.
|
||||
By downloading or using this software, you are agreeing to be bound by
|
||||
the terms of this License. If you do not or cannot agree to the terms
|
||||
of this License, please do not download or use the software.
|
||||
|
||||
1. General; Definitions. This License applies to any program or other
|
||||
work which Apple Computer, Inc. ("Apple") makes publicly available and
|
||||
which contains a notice placed by Apple identifying such program or
|
||||
work as "Original Code" and stating that it is subject to the terms of
|
||||
this Apple Public Source License version 2.0 ("License"). As used in
|
||||
this License:
|
||||
|
||||
1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is
|
||||
the grantor of rights, (i) claims of patents that are now or hereafter
|
||||
acquired, owned by or assigned to Apple and (ii) that cover subject
|
||||
matter contained in the Original Code, but only to the extent
|
||||
necessary to use, reproduce and/or distribute the Original Code
|
||||
without infringement; and (b) in the case where You are the grantor of
|
||||
rights, (i) claims of patents that are now or hereafter acquired,
|
||||
owned by or assigned to You and (ii) that cover subject matter in Your
|
||||
Modifications, taken alone or in combination with Original Code.
|
||||
|
||||
1.2 "Contributor" means any person or entity that creates or
|
||||
contributes to the creation of Modifications.
|
||||
|
||||
1.3 "Covered Code" means the Original Code, Modifications, the
|
||||
combination of Original Code and any Modifications, and/or any
|
||||
respective portions thereof.
|
||||
|
||||
1.4 "Externally Deploy" means: (a) to sublicense, distribute or
|
||||
otherwise make Covered Code available, directly or indirectly, to
|
||||
anyone other than You; and/or (b) to use Covered Code, alone or as
|
||||
part of a Larger Work, in any way to provide a service, including but
|
||||
not limited to delivery of content, through electronic communication
|
||||
with a client other than You.
|
||||
|
||||
1.5 "Larger Work" means a work which combines Covered Code or portions
|
||||
thereof with code not governed by the terms of this License.
|
||||
|
||||
1.6 "Modifications" mean any addition to, deletion from, and/or change
|
||||
to, the substance and/or structure of the Original Code, any previous
|
||||
Modifications, the combination of Original Code and any previous
|
||||
Modifications, and/or any respective portions thereof. When code is
|
||||
released as a series of files, a Modification is: (a) any addition to
|
||||
or deletion from the contents of a file containing Covered Code;
|
||||
and/or (b) any new file or other representation of computer program
|
||||
statements that contains any part of Covered Code.
|
||||
|
||||
1.7 "Original Code" means (a) the Source Code of a program or other
|
||||
work as originally made available by Apple under this License,
|
||||
including the Source Code of any updates or upgrades to such programs
|
||||
or works made available by Apple under this License, and that has been
|
||||
expressly identified by Apple as such in the header file(s) of such
|
||||
work; and (b) the object code compiled from such Source Code and
|
||||
originally made available by Apple under this License.
|
||||
|
||||
1.8 "Source Code" means the human readable form of a program or other
|
||||
work that is suitable for making modifications to it, including all
|
||||
modules it contains, plus any associated interface definition files,
|
||||
scripts used to control compilation and installation of an executable
|
||||
(object code).
|
||||
|
||||
1.9 "You" or "Your" means an individual or a legal entity exercising
|
||||
rights under this License. For legal entities, "You" or "Your"
|
||||
includes any entity which controls, is controlled by, or is under
|
||||
common control with, You, where "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of fifty percent
|
||||
(50%) or more of the outstanding shares or beneficial ownership of
|
||||
such entity.
|
||||
|
||||
2. Permitted Uses; Conditions & Restrictions. Subject to the terms
|
||||
and conditions of this License, Apple hereby grants You, effective on
|
||||
the date You accept this License and download the Original Code, a
|
||||
world-wide, royalty-free, non-exclusive license, to the extent of
|
||||
Apple's Applicable Patent Rights and copyrights covering the Original
|
||||
Code, to do the following:
|
||||
|
||||
2.1 Unmodified Code. You may use, reproduce, display, perform,
|
||||
internally distribute within Your organization, and Externally Deploy
|
||||
verbatim, unmodified copies of the Original Code, for commercial or
|
||||
non-commercial purposes, provided that in each instance:
|
||||
|
||||
(a) You must retain and reproduce in all copies of Original Code the
|
||||
copyright and other proprietary notices and disclaimers of Apple as
|
||||
they appear in the Original Code, and keep intact all notices in the
|
||||
Original Code that refer to this License; and
|
||||
|
||||
(b) You must include a copy of this License with every copy of Source
|
||||
Code of Covered Code and documentation You distribute or Externally
|
||||
Deploy, and You may not offer or impose any terms on such Source Code
|
||||
that alter or restrict this License or the recipients' rights
|
||||
hereunder, except as permitted under Section 6.
|
||||
|
||||
2.2 Modified Code. You may modify Covered Code and use, reproduce,
|
||||
display, perform, internally distribute within Your organization, and
|
||||
Externally Deploy Your Modifications and Covered Code, for commercial
|
||||
or non-commercial purposes, provided that in each instance You also
|
||||
meet all of these conditions:
|
||||
|
||||
(a) You must satisfy all the conditions of Section 2.1 with respect to
|
||||
the Source Code of the Covered Code;
|
||||
|
||||
(b) You must duplicate, to the extent it does not already exist, the
|
||||
notice in Exhibit A in each file of the Source Code of all Your
|
||||
Modifications, and cause the modified files to carry prominent notices
|
||||
stating that You changed the files and the date of any change; and
|
||||
|
||||
(c) If You Externally Deploy Your Modifications, You must make
|
||||
Source Code of all Your Externally Deployed Modifications either
|
||||
available to those to whom You have Externally Deployed Your
|
||||
Modifications, or publicly available. Source Code of Your Externally
|
||||
Deployed Modifications must be released under the terms set forth in
|
||||
this License, including the license grants set forth in Section 3
|
||||
below, for as long as you Externally Deploy the Covered Code or twelve
|
||||
(12) months from the date of initial External Deployment, whichever is
|
||||
longer. You should preferably distribute the Source Code of Your
|
||||
Externally Deployed Modifications electronically (e.g. download from a
|
||||
web site).
|
||||
|
||||
2.3 Distribution of Executable Versions. In addition, if You
|
||||
Externally Deploy Covered Code (Original Code and/or Modifications) in
|
||||
object code, executable form only, You must include a prominent
|
||||
notice, in the code itself as well as in related documentation,
|
||||
stating that Source Code of the Covered Code is available under the
|
||||
terms of this License with information on how and where to obtain such
|
||||
Source Code.
|
||||
|
||||
2.4 Third Party Rights. You expressly acknowledge and agree that
|
||||
although Apple and each Contributor grants the licenses to their
|
||||
respective portions of the Covered Code set forth herein, no
|
||||
assurances are provided by Apple or any Contributor that the Covered
|
||||
Code does not infringe the patent or other intellectual property
|
||||
rights of any other entity. Apple and each Contributor disclaim any
|
||||
liability to You for claims brought by any other entity based on
|
||||
infringement of intellectual property rights or otherwise. As a
|
||||
condition to exercising the rights and licenses granted hereunder, You
|
||||
hereby assume sole responsibility to secure any other intellectual
|
||||
property rights needed, if any. For example, if a third party patent
|
||||
license is required to allow You to distribute the Covered Code, it is
|
||||
Your responsibility to acquire that license before distributing the
|
||||
Covered Code.
|
||||
|
||||
3. Your Grants. In consideration of, and as a condition to, the
|
||||
licenses granted to You under this License, You hereby grant to any
|
||||
person or entity receiving or distributing Covered Code under this
|
||||
License a non-exclusive, royalty-free, perpetual, irrevocable license,
|
||||
under Your Applicable Patent Rights and other intellectual property
|
||||
rights (other than patent) owned or controlled by You, to use,
|
||||
reproduce, display, perform, modify, sublicense, distribute and
|
||||
Externally Deploy Your Modifications of the same scope and extent as
|
||||
Apple's licenses under Sections 2.1 and 2.2 above.
|
||||
|
||||
4. Larger Works. You may create a Larger Work by combining Covered
|
||||
Code with other code not governed by the terms of this License and
|
||||
distribute the Larger Work as a single product. In each such instance,
|
||||
You must make sure the requirements of this License are fulfilled for
|
||||
the Covered Code or any portion thereof.
|
||||
|
||||
5. Limitations on Patent License. Except as expressly stated in
|
||||
Section 2, no other patent rights, express or implied, are granted by
|
||||
Apple herein. Modifications and/or Larger Works may require additional
|
||||
patent licenses from Apple which Apple may grant in its sole
|
||||
discretion.
|
||||
|
||||
6. Additional Terms. You may choose to offer, and to charge a fee for,
|
||||
warranty, support, indemnity or liability obligations and/or other
|
||||
rights consistent with the scope of the license granted herein
|
||||
("Additional Terms") to one or more recipients of Covered Code.
|
||||
However, You may do so only on Your own behalf and as Your sole
|
||||
responsibility, and not on behalf of Apple or any Contributor. You
|
||||
must obtain the recipient's agreement that any such Additional Terms
|
||||
are offered by You alone, and You hereby agree to indemnify, defend
|
||||
and hold Apple and every Contributor harmless for any liability
|
||||
incurred by or claims asserted against Apple or such Contributor by
|
||||
reason of any such Additional Terms.
|
||||
|
||||
7. Versions of the License. Apple may publish revised and/or new
|
||||
versions of this License from time to time. Each version will be given
|
||||
a distinguishing version number. Once Original Code has been published
|
||||
under a particular version of this License, You may continue to use it
|
||||
under the terms of that version. You may also choose to use such
|
||||
Original Code under the terms of any subsequent version of this
|
||||
License published by Apple. No one other than Apple has the right to
|
||||
modify the terms applicable to Covered Code created under this
|
||||
License.
|
||||
|
||||
8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in
|
||||
part pre-release, untested, or not fully tested works. The Covered
|
||||
Code may contain errors that could cause failures or loss of data, and
|
||||
may be incomplete or contain inaccuracies. You expressly acknowledge
|
||||
and agree that use of the Covered Code, or any portion thereof, is at
|
||||
Your sole and entire risk. THE COVERED CODE IS PROVIDED "AS IS" AND
|
||||
WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND AND APPLE AND
|
||||
APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE
|
||||
PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM
|
||||
ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT
|
||||
NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF
|
||||
MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR
|
||||
PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD
|
||||
PARTY RIGHTS. APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST
|
||||
INTERFERENCE WITH YOUR ENJOYMENT OF THE COVERED CODE, THAT THE
|
||||
FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR REQUIREMENTS,
|
||||
THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR
|
||||
ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO
|
||||
ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE
|
||||
AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY.
|
||||
You acknowledge that the Covered Code is not intended for use in the
|
||||
operation of nuclear facilities, aircraft navigation, communication
|
||||
systems, or air traffic control machines in which case the failure of
|
||||
the Covered Code could lead to death, personal injury, or severe
|
||||
physical or environmental damage.
|
||||
|
||||
9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO
|
||||
EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL,
|
||||
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING
|
||||
TO THIS LICENSE OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR
|
||||
ANY PORTION THEREOF, WHETHER UNDER A THEORY OF CONTRACT, WARRANTY,
|
||||
TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF
|
||||
APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY
|
||||
REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF
|
||||
INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY
|
||||
TO YOU. In no event shall Apple's total liability to You for all
|
||||
damages (other than as may be required by applicable law) under this
|
||||
License exceed the amount of fifty dollars ($50.00).
|
||||
|
||||
10. Trademarks. This License does not grant any rights to use the
|
||||
trademarks or trade names "Apple", "Apple Computer", "Mac", "Mac OS",
|
||||
"QuickTime", "QuickTime Streaming Server" or any other trademarks,
|
||||
service marks, logos or trade names belonging to Apple (collectively
|
||||
"Apple Marks") or to any trademark, service mark, logo or trade name
|
||||
belonging to any Contributor. You agree not to use any Apple Marks in
|
||||
or as part of the name of products derived from the Original Code or
|
||||
to endorse or promote products derived from the Original Code other
|
||||
than as expressly permitted by and in strict compliance at all times
|
||||
with Apple's third party trademark usage guidelines which are posted
|
||||
at http://www.apple.com/legal/guidelinesfor3rdparties.html.
|
||||
|
||||
11. Ownership. Subject to the licenses granted under this License,
|
||||
each Contributor retains all rights, title and interest in and to any
|
||||
Modifications made by such Contributor. Apple retains all rights,
|
||||
title and interest in and to the Original Code and any Modifications
|
||||
made by or on behalf of Apple ("Apple Modifications"), and such Apple
|
||||
Modifications will not be automatically subject to this License. Apple
|
||||
may, at its sole discretion, choose to license such Apple
|
||||
Modifications under this License, or on different terms from those
|
||||
contained in this License or may choose not to license them at all.
|
||||
|
||||
12. Termination.
|
||||
|
||||
12.1 Termination. This License and the rights granted hereunder will
|
||||
terminate:
|
||||
|
||||
(a) automatically without notice from Apple if You fail to comply with
|
||||
any term(s) of this License and fail to cure such breach within 30
|
||||
days of becoming aware of such breach;
|
||||
|
||||
(b) immediately in the event of the circumstances described in Section
|
||||
13.5(b); or
|
||||
|
||||
(c) automatically without notice from Apple if You, at any time during
|
||||
the term of this License, commence an action for patent infringement
|
||||
against Apple; provided that Apple did not first commence
|
||||
an action for patent infringement against You in that instance.
|
||||
|
||||
12.2 Effect of Termination. Upon termination, You agree to immediately
|
||||
stop any further use, reproduction, modification, sublicensing and
|
||||
distribution of the Covered Code. All sublicenses to the Covered Code
|
||||
which have been properly granted prior to termination shall survive
|
||||
any termination of this License. Provisions which, by their nature,
|
||||
should remain in effect beyond the termination of this License shall
|
||||
survive, including but not limited to Sections 3, 5, 8, 9, 10, 11,
|
||||
12.2 and 13. No party will be liable to any other for compensation,
|
||||
indemnity or damages of any sort solely as a result of terminating
|
||||
this License in accordance with its terms, and termination of this
|
||||
License will be without prejudice to any other right or remedy of
|
||||
any party.
|
||||
|
||||
13. Miscellaneous.
|
||||
|
||||
13.1 Government End Users. The Covered Code is a "commercial item" as
|
||||
defined in FAR 2.101. Government software and technical data rights in
|
||||
the Covered Code include only those rights customarily provided to the
|
||||
public as defined in this License. This customary commercial license
|
||||
in technical data and software is provided in accordance with FAR
|
||||
12.211 (Technical Data) and 12.212 (Computer Software) and, for
|
||||
Department of Defense purchases, DFAR 252.227-7015 (Technical Data --
|
||||
Commercial Items) and 227.7202-3 (Rights in Commercial Computer
|
||||
Software or Computer Software Documentation). Accordingly, all U.S.
|
||||
Government End Users acquire Covered Code with only those rights set
|
||||
forth herein.
|
||||
|
||||
13.2 Relationship of Parties. This License will not be construed as
|
||||
creating an agency, partnership, joint venture or any other form of
|
||||
legal association between or among You, Apple or any Contributor, and
|
||||
You will not represent to the contrary, whether expressly, by
|
||||
implication, appearance or otherwise.
|
||||
|
||||
13.3 Independent Development. Nothing in this License will impair
|
||||
Apple's right to acquire, license, develop, have others develop for
|
||||
it, market and/or distribute technology or products that perform the
|
||||
same or similar functions as, or otherwise compete with,
|
||||
Modifications, Larger Works, technology or products that You may
|
||||
develop, produce, market or distribute.
|
||||
|
||||
13.4 Waiver; Construction. Failure by Apple or any Contributor to
|
||||
enforce any provision of this License will not be deemed a waiver of
|
||||
future enforcement of that or any other provision. Any law or
|
||||
regulation which provides that the language of a contract shall be
|
||||
construed against the drafter will not apply to this License.
|
||||
|
||||
13.5 Severability. (a) If for any reason a court of competent
|
||||
jurisdiction finds any provision of this License, or portion thereof,
|
||||
to be unenforceable, that provision of the License will be enforced to
|
||||
the maximum extent permissible so as to effect the economic benefits
|
||||
and intent of the parties, and the remainder of this License will
|
||||
continue in full force and effect. (b) Notwithstanding the foregoing,
|
||||
if applicable law prohibits or restricts You from fully and/or
|
||||
specifically complying with Sections 2 and/or 3 or prevents the
|
||||
enforceability of either of those Sections, this License will
|
||||
immediately terminate and You must immediately discontinue any use of
|
||||
the Covered Code and destroy all copies of it that are in your
|
||||
possession or control.
|
||||
|
||||
13.6 Dispute Resolution. Any litigation or other dispute resolution
|
||||
between You and Apple relating to this License shall take place in the
|
||||
Northern District of California, and You and Apple hereby consent to
|
||||
the personal jurisdiction of, and venue in, the state and federal
|
||||
courts within that District with respect to this License. The
|
||||
application of the United Nations Convention on Contracts for the
|
||||
International Sale of Goods is expressly excluded.
|
||||
|
||||
13.7 Entire Agreement; Governing Law. This License constitutes the
|
||||
entire agreement between the parties with respect to the subject
|
||||
matter hereof. This License shall be governed by the laws of the
|
||||
United States and the State of California, except that body of
|
||||
California law concerning conflicts of law.
|
||||
|
||||
Where You are located in the province of Quebec, Canada, the following
|
||||
clause applies: The parties hereby confirm that they have requested
|
||||
that this License and all related documents be drafted in English. Les
|
||||
parties ont exige que le present contrat et tous les documents
|
||||
connexes soient rediges en anglais.
|
||||
|
||||
EXHIBIT A.
|
||||
|
||||
"Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
|
||||
Reserved.
|
||||
|
||||
This file contains Original Code and/or Modifications of Original Code
|
||||
as defined in and that are subject to the Apple Public Source License
|
||||
Version 2.0 (the 'License'). You may not use this file except in
|
||||
compliance with the License. Please obtain a copy of the License at
|
||||
http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
file.
|
||||
|
||||
The Original Code and all software distributed under the License are
|
||||
distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
Please see the License for the specific language governing rights and
|
||||
limitations under the License."
|
@ -0,0 +1,802 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2010 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. The rights granted to you under the License
|
||||
* may not be used to create, or enable the creation or redistribution of,
|
||||
* unlawful or unlicensed copies of an Apple operating system, or to
|
||||
* circumvent, violate, or enable the circumvention or violation of, any
|
||||
* terms of an Apple operating system software license agreement.
|
||||
*
|
||||
* Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
/* $NetBSD: tree.h,v 1.13 2006/08/27 22:32:38 christos Exp $ */
|
||||
/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */
|
||||
/*
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _LIBKERN_TREE_H_
|
||||
#define _LIBKERN_TREE_H_
|
||||
|
||||
/*
|
||||
* This file defines data structures for different types of trees:
|
||||
* splay trees and red-black trees.
|
||||
*
|
||||
* A splay tree is a self-organizing data structure. Every operation
|
||||
* on the tree causes a splay to happen. The splay moves the requested
|
||||
* node to the root of the tree and partly rebalances it.
|
||||
*
|
||||
* This has the benefit that request locality causes faster lookups as
|
||||
* the requested nodes move to the top of the tree. On the other hand,
|
||||
* every lookup causes memory writes.
|
||||
*
|
||||
* The Balance Theorem bounds the total access time for m operations
|
||||
* and n inserts on an initially empty tree as O((m + n)lg n). The
|
||||
* amortized cost for a sequence of m accesses to a splay tree is O(lg n);
|
||||
*
|
||||
* A red-black tree is a binary search tree with the node color as an
|
||||
* extra attribute. It fulfills a set of conditions:
|
||||
* - every search path from the root to a leaf consists of the
|
||||
* same number of black nodes,
|
||||
* - each red node (except for the root) has a black parent,
|
||||
* - each leaf node is black.
|
||||
*
|
||||
* Every operation on a red-black tree is bounded as O(lg n).
|
||||
* The maximum height of a red-black tree is 2lg (n+1).
|
||||
*/
|
||||
|
||||
#define SPLAY_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *sph_root; /* root of the tree */ \
|
||||
}
|
||||
|
||||
#define SPLAY_INITIALIZER(root) \
|
||||
{ NULL }
|
||||
|
||||
#define SPLAY_INIT(root) do { \
|
||||
(root)->sph_root = NULL; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *spe_left; /* left element */ \
|
||||
struct type *spe_right; /* right element */ \
|
||||
}
|
||||
|
||||
#define SPLAY_LEFT(elm, field) (elm)->field.spe_left
|
||||
#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right
|
||||
#define SPLAY_ROOT(head) (head)->sph_root
|
||||
#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL)
|
||||
|
||||
/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
|
||||
#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \
|
||||
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
|
||||
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
|
||||
(head)->sph_root = tmp; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
|
||||
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
|
||||
(head)->sph_root = tmp; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_LINKLEFT(head, tmp, field) do { \
|
||||
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
|
||||
tmp = (head)->sph_root; \
|
||||
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_LINKRIGHT(head, tmp, field) do { \
|
||||
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
|
||||
tmp = (head)->sph_root; \
|
||||
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
|
||||
SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
|
||||
SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
|
||||
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
/* Generates prototypes and inline functions */
|
||||
|
||||
#define SPLAY_PROTOTYPE(name, type, field, cmp) \
|
||||
void name##_SPLAY(struct name *, struct type *); \
|
||||
void name##_SPLAY_MINMAX(struct name *, int); \
|
||||
struct type *name##_SPLAY_INSERT(struct name *, struct type *); \
|
||||
struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \
|
||||
\
|
||||
/* Finds the node with the same key as elm */ \
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_FIND(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
if (SPLAY_EMPTY(head)) \
|
||||
return(NULL); \
|
||||
name##_SPLAY(head, elm); \
|
||||
if ((cmp)(elm, (head)->sph_root) == 0) \
|
||||
return (head->sph_root); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_NEXT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
name##_SPLAY(head, elm); \
|
||||
if (SPLAY_RIGHT(elm, field) != NULL) { \
|
||||
elm = SPLAY_RIGHT(elm, field); \
|
||||
while (SPLAY_LEFT(elm, field) != NULL) { \
|
||||
elm = SPLAY_LEFT(elm, field); \
|
||||
} \
|
||||
} else \
|
||||
elm = NULL; \
|
||||
return (elm); \
|
||||
} \
|
||||
\
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_MIN_MAX(struct name *head, int val) \
|
||||
{ \
|
||||
name##_SPLAY_MINMAX(head, val); \
|
||||
return (SPLAY_ROOT(head)); \
|
||||
}
|
||||
|
||||
/* Main splay operation.
|
||||
* Moves node close to the key of elm to top
|
||||
*/
|
||||
#define SPLAY_GENERATE(name, type, field, cmp) \
|
||||
struct type * \
|
||||
name##_SPLAY_INSERT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
if (SPLAY_EMPTY(head)) { \
|
||||
SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \
|
||||
} else { \
|
||||
int __comp; \
|
||||
name##_SPLAY(head, elm); \
|
||||
__comp = (cmp)(elm, (head)->sph_root); \
|
||||
if(__comp < 0) { \
|
||||
SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
|
||||
SPLAY_RIGHT(elm, field) = (head)->sph_root; \
|
||||
SPLAY_LEFT((head)->sph_root, field) = NULL; \
|
||||
} else if (__comp > 0) { \
|
||||
SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
|
||||
SPLAY_LEFT(elm, field) = (head)->sph_root; \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = NULL; \
|
||||
} else \
|
||||
return ((head)->sph_root); \
|
||||
} \
|
||||
(head)->sph_root = (elm); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
struct type * \
|
||||
name##_SPLAY_REMOVE(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *__tmp; \
|
||||
if (SPLAY_EMPTY(head)) \
|
||||
return (NULL); \
|
||||
name##_SPLAY(head, elm); \
|
||||
if ((cmp)(elm, (head)->sph_root) == 0) { \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
|
||||
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
|
||||
} else { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
|
||||
name##_SPLAY(head, elm); \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
|
||||
} \
|
||||
return (elm); \
|
||||
} \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
name##_SPLAY(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type __node, *__left, *__right, *__tmp; \
|
||||
int __comp; \
|
||||
\
|
||||
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
|
||||
__left = __right = &__node; \
|
||||
\
|
||||
while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \
|
||||
if (__comp < 0) { \
|
||||
__tmp = SPLAY_LEFT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if ((cmp)(elm, __tmp) < 0){ \
|
||||
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKLEFT(head, __right, field); \
|
||||
} else if (__comp > 0) { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if ((cmp)(elm, __tmp) > 0){ \
|
||||
SPLAY_ROTATE_LEFT(head, __tmp, field); \
|
||||
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKRIGHT(head, __left, field); \
|
||||
} \
|
||||
} \
|
||||
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
|
||||
} \
|
||||
\
|
||||
/* Splay with either the minimum or the maximum element \
|
||||
* Used to find minimum or maximum element in tree. \
|
||||
*/ \
|
||||
void name##_SPLAY_MINMAX(struct name *head, int __comp) \
|
||||
{ \
|
||||
struct type __node, *__left, *__right, *__tmp; \
|
||||
\
|
||||
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
|
||||
__left = __right = &__node; \
|
||||
\
|
||||
while (1) { \
|
||||
if (__comp < 0) { \
|
||||
__tmp = SPLAY_LEFT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if (__comp < 0){ \
|
||||
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKLEFT(head, __right, field); \
|
||||
} else if (__comp > 0) { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if (__comp > 0) { \
|
||||
SPLAY_ROTATE_LEFT(head, __tmp, field); \
|
||||
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKRIGHT(head, __left, field); \
|
||||
} \
|
||||
} \
|
||||
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
|
||||
}
|
||||
|
||||
#define SPLAY_NEGINF -1
|
||||
#define SPLAY_INF 1
|
||||
|
||||
#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y)
|
||||
#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y)
|
||||
#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y)
|
||||
#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y)
|
||||
#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \
|
||||
: name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
|
||||
#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \
|
||||
: name##_SPLAY_MIN_MAX(x, SPLAY_INF))
|
||||
|
||||
#define SPLAY_FOREACH(x, name, head) \
|
||||
for ((x) = SPLAY_MIN(name, head); \
|
||||
(x) != NULL; \
|
||||
(x) = SPLAY_NEXT(name, head, x))
|
||||
|
||||
/* Macros that define a red-black tree */
|
||||
#define RB_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *rbh_root; /* root of the tree */ \
|
||||
}
|
||||
|
||||
#define RB_INITIALIZER(root) \
|
||||
{ NULL }
|
||||
|
||||
#define RB_INIT(root) do { \
|
||||
(root)->rbh_root = NULL; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define RB_BLACK 0
|
||||
#define RB_RED 1
|
||||
#define RB_PLACEHOLDER NULL
|
||||
#define RB_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *rbe_left; /* left element */ \
|
||||
struct type *rbe_right; /* right element */ \
|
||||
struct type *rbe_parent; /* parent element */ \
|
||||
}
|
||||
|
||||
#define RB_COLOR_MASK (uintptr_t)0x1
|
||||
#define RB_LEFT(elm, field) (elm)->field.rbe_left
|
||||
#define RB_RIGHT(elm, field) (elm)->field.rbe_right
|
||||
#define _RB_PARENT(elm, field) (elm)->field.rbe_parent
|
||||
#define RB_ROOT(head) (head)->rbh_root
|
||||
#define RB_EMPTY(head) (RB_ROOT(head) == NULL)
|
||||
|
||||
#define RB_SET(name, elm, parent, field) do { \
|
||||
name##_RB_SETPARENT(elm, parent); \
|
||||
RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
|
||||
name##_RB_SETCOLOR(elm, RB_RED); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define RB_SET_BLACKRED(name, black, red, field) do { \
|
||||
name##_RB_SETCOLOR(black, RB_BLACK); \
|
||||
name##_RB_SETCOLOR(red, RB_RED); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#ifndef RB_AUGMENT
|
||||
#define RB_AUGMENT(x) (void)(x)
|
||||
#endif
|
||||
|
||||
#define RB_ROTATE_LEFT(name, head, elm, tmp, field) do { \
|
||||
(tmp) = RB_RIGHT(elm, field); \
|
||||
if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \
|
||||
name##_RB_SETPARENT(RB_LEFT(tmp, field),(elm)); \
|
||||
} \
|
||||
RB_AUGMENT(elm); \
|
||||
if (name##_RB_SETPARENT(tmp, name##_RB_GETPARENT(elm)) != NULL) { \
|
||||
if ((elm) == RB_LEFT(name##_RB_GETPARENT(elm), field)) \
|
||||
RB_LEFT(name##_RB_GETPARENT(elm), field) = (tmp); \
|
||||
else \
|
||||
RB_RIGHT(name##_RB_GETPARENT(elm), field) = (tmp); \
|
||||
} else \
|
||||
(head)->rbh_root = (tmp); \
|
||||
RB_LEFT(tmp, field) = (elm); \
|
||||
name##_RB_SETPARENT(elm, (tmp)); \
|
||||
RB_AUGMENT(tmp); \
|
||||
if ((name##_RB_GETPARENT(tmp))) \
|
||||
RB_AUGMENT(name##_RB_GETPARENT(tmp)); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define RB_ROTATE_RIGHT(name, head, elm, tmp, field) do { \
|
||||
(tmp) = RB_LEFT(elm, field); \
|
||||
if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \
|
||||
name##_RB_SETPARENT(RB_RIGHT(tmp, field), (elm)); \
|
||||
} \
|
||||
RB_AUGMENT(elm); \
|
||||
if (name##_RB_SETPARENT(tmp, name##_RB_GETPARENT(elm)) != NULL) { \
|
||||
if ((elm) == RB_LEFT(name##_RB_GETPARENT(elm), field)) \
|
||||
RB_LEFT(name##_RB_GETPARENT(elm), field) = (tmp); \
|
||||
else \
|
||||
RB_RIGHT(name##_RB_GETPARENT(elm), field) = (tmp); \
|
||||
} else \
|
||||
(head)->rbh_root = (tmp); \
|
||||
RB_RIGHT(tmp, field) = (elm); \
|
||||
name##_RB_SETPARENT(elm, tmp); \
|
||||
RB_AUGMENT(tmp); \
|
||||
if ((name##_RB_GETPARENT(tmp))) \
|
||||
RB_AUGMENT(name##_RB_GETPARENT(tmp)); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
/* Generates prototypes and inline functions */
|
||||
#define RB_PROTOTYPE(name, type, field, cmp) \
|
||||
void name##_RB_INSERT_COLOR(struct name *, struct type *); \
|
||||
void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
|
||||
struct type *name##_RB_REMOVE(struct name *, struct type *); \
|
||||
struct type *name##_RB_INSERT(struct name *, struct type *); \
|
||||
struct type *name##_RB_FIND(struct name *, struct type *); \
|
||||
struct type *name##_RB_NEXT(struct type *); \
|
||||
struct type *name##_RB_MINMAX(struct name *, int); \
|
||||
struct type *name##_RB_GETPARENT(struct type*); \
|
||||
struct type *name##_RB_SETPARENT(struct type*, struct type*); \
|
||||
int name##_RB_GETCOLOR(struct type*); \
|
||||
void name##_RB_SETCOLOR(struct type*,int);
|
||||
|
||||
/* Generates prototypes (with storage class) and inline functions */
|
||||
#define RB_PROTOTYPE_SC(_sc_, name, type, field, cmp) \
|
||||
_sc_ void name##_RB_INSERT_COLOR(struct name *, struct type *); \
|
||||
_sc_ void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *); \
|
||||
_sc_ struct type *name##_RB_REMOVE(struct name *, struct type *); \
|
||||
_sc_ struct type *name##_RB_INSERT(struct name *, struct type *); \
|
||||
_sc_ struct type *name##_RB_FIND(struct name *, struct type *); \
|
||||
_sc_ struct type *name##_RB_NEXT(struct type *); \
|
||||
_sc_ struct type *name##_RB_MINMAX(struct name *, int); \
|
||||
_sc_ struct type *name##_RB_GETPARENT(struct type*); \
|
||||
_sc_ struct type *name##_RB_SETPARENT(struct type*, struct type*); \
|
||||
_sc_ int name##_RB_GETCOLOR(struct type*); \
|
||||
_sc_ void name##_RB_SETCOLOR(struct type*,int);
|
||||
|
||||
|
||||
/* Main rb operation.
|
||||
* Moves node close to the key of elm to top
|
||||
*/
|
||||
#define RB_GENERATE(name, type, field, cmp) \
|
||||
struct type *name##_RB_GETPARENT(struct type *elm) { \
|
||||
struct type *parent = _RB_PARENT(elm, field); \
|
||||
if( parent != NULL) { \
|
||||
parent = (struct type*)((uintptr_t)parent & ~RB_COLOR_MASK);\
|
||||
return( (struct type*) ( (parent == (struct type*) RB_PLACEHOLDER) ? NULL: parent));\
|
||||
} \
|
||||
return((struct type*)NULL); \
|
||||
} \
|
||||
int name##_RB_GETCOLOR(struct type *elm) { \
|
||||
int color = 0; \
|
||||
color = (int)((uintptr_t)_RB_PARENT(elm,field) & RB_COLOR_MASK);\
|
||||
return(color); \
|
||||
} \
|
||||
void name##_RB_SETCOLOR(struct type *elm,int color) { \
|
||||
struct type *parent = name##_RB_GETPARENT(elm); \
|
||||
if(parent == (struct type*)NULL) \
|
||||
parent = (struct type*) RB_PLACEHOLDER; \
|
||||
_RB_PARENT(elm, field) = (struct type*)((uintptr_t)parent | (unsigned int)color);\
|
||||
} \
|
||||
struct type *name##_RB_SETPARENT(struct type *elm, struct type *parent) { \
|
||||
int color = name##_RB_GETCOLOR(elm); \
|
||||
_RB_PARENT(elm, field) = parent; \
|
||||
if(color) name##_RB_SETCOLOR(elm, color); \
|
||||
return(name##_RB_GETPARENT(elm)); \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *parent, *gparent, *tmp; \
|
||||
while ((parent = name##_RB_GETPARENT(elm)) != NULL && \
|
||||
name##_RB_GETCOLOR(parent) == RB_RED) { \
|
||||
gparent = name##_RB_GETPARENT(parent); \
|
||||
if (parent == RB_LEFT(gparent, field)) { \
|
||||
tmp = RB_RIGHT(gparent, field); \
|
||||
if (tmp && name##_RB_GETCOLOR(tmp) == RB_RED) { \
|
||||
name##_RB_SETCOLOR(tmp, RB_BLACK); \
|
||||
RB_SET_BLACKRED(name, parent, gparent, field);\
|
||||
elm = gparent; \
|
||||
continue; \
|
||||
} \
|
||||
if (RB_RIGHT(parent, field) == elm) { \
|
||||
RB_ROTATE_LEFT(name, head, parent, tmp, field);\
|
||||
tmp = parent; \
|
||||
parent = elm; \
|
||||
elm = tmp; \
|
||||
} \
|
||||
RB_SET_BLACKRED(name, parent, gparent, field); \
|
||||
RB_ROTATE_RIGHT(name,head, gparent, tmp, field); \
|
||||
} else { \
|
||||
tmp = RB_LEFT(gparent, field); \
|
||||
if (tmp && name##_RB_GETCOLOR(tmp) == RB_RED) { \
|
||||
name##_RB_SETCOLOR(tmp, RB_BLACK); \
|
||||
RB_SET_BLACKRED(name, parent, gparent, field);\
|
||||
elm = gparent; \
|
||||
continue; \
|
||||
} \
|
||||
if (RB_LEFT(parent, field) == elm) { \
|
||||
RB_ROTATE_RIGHT(name, head, parent, tmp, field);\
|
||||
tmp = parent; \
|
||||
parent = elm; \
|
||||
elm = tmp; \
|
||||
} \
|
||||
RB_SET_BLACKRED(name, parent, gparent, field); \
|
||||
RB_ROTATE_LEFT(name, head, gparent, tmp, field); \
|
||||
} \
|
||||
} \
|
||||
name##_RB_SETCOLOR(head->rbh_root, RB_BLACK); \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp; \
|
||||
while ((elm == NULL || name##_RB_GETCOLOR(elm) == RB_BLACK) && \
|
||||
elm != RB_ROOT(head)) { \
|
||||
if (RB_LEFT(parent, field) == elm) { \
|
||||
tmp = RB_RIGHT(parent, field); \
|
||||
if (name##_RB_GETCOLOR(tmp) == RB_RED) { \
|
||||
RB_SET_BLACKRED(name, tmp, parent, field); \
|
||||
RB_ROTATE_LEFT(name, head, parent, tmp, field);\
|
||||
tmp = RB_RIGHT(parent, field); \
|
||||
} \
|
||||
if ((RB_LEFT(tmp, field) == NULL || \
|
||||
name##_RB_GETCOLOR(RB_LEFT(tmp, field)) == RB_BLACK) &&\
|
||||
(RB_RIGHT(tmp, field) == NULL || \
|
||||
name##_RB_GETCOLOR(RB_RIGHT(tmp, field)) == RB_BLACK)) {\
|
||||
name##_RB_SETCOLOR(tmp, RB_RED); \
|
||||
elm = parent; \
|
||||
parent = name##_RB_GETPARENT(elm); \
|
||||
} else { \
|
||||
if (RB_RIGHT(tmp, field) == NULL || \
|
||||
name##_RB_GETCOLOR(RB_RIGHT(tmp, field)) == RB_BLACK) {\
|
||||
struct type *oleft; \
|
||||
if ((oleft = RB_LEFT(tmp, field)) \
|
||||
!= NULL) \
|
||||
name##_RB_SETCOLOR(oleft, RB_BLACK);\
|
||||
name##_RB_SETCOLOR(tmp, RB_RED); \
|
||||
RB_ROTATE_RIGHT(name, head, tmp, oleft, field);\
|
||||
tmp = RB_RIGHT(parent, field); \
|
||||
} \
|
||||
name##_RB_SETCOLOR(tmp, (name##_RB_GETCOLOR(parent)));\
|
||||
name##_RB_SETCOLOR(parent, RB_BLACK); \
|
||||
if (RB_RIGHT(tmp, field)) \
|
||||
name##_RB_SETCOLOR(RB_RIGHT(tmp, field),RB_BLACK);\
|
||||
RB_ROTATE_LEFT(name, head, parent, tmp, field);\
|
||||
elm = RB_ROOT(head); \
|
||||
break; \
|
||||
} \
|
||||
} else { \
|
||||
tmp = RB_LEFT(parent, field); \
|
||||
if (name##_RB_GETCOLOR(tmp) == RB_RED) { \
|
||||
RB_SET_BLACKRED(name, tmp, parent, field); \
|
||||
RB_ROTATE_RIGHT(name, head, parent, tmp, field);\
|
||||
tmp = RB_LEFT(parent, field); \
|
||||
} \
|
||||
if ((RB_LEFT(tmp, field) == NULL || \
|
||||
name##_RB_GETCOLOR(RB_LEFT(tmp, field)) == RB_BLACK) &&\
|
||||
(RB_RIGHT(tmp, field) == NULL || \
|
||||
name##_RB_GETCOLOR(RB_RIGHT(tmp, field)) == RB_BLACK)) {\
|
||||
name##_RB_SETCOLOR(tmp, RB_RED); \
|
||||
elm = parent; \
|
||||
parent = name##_RB_GETPARENT(elm); \
|
||||
} else { \
|
||||
if (RB_LEFT(tmp, field) == NULL || \
|
||||
name##_RB_GETCOLOR(RB_LEFT(tmp, field)) == RB_BLACK) {\
|
||||
struct type *oright; \
|
||||
if ((oright = RB_RIGHT(tmp, field)) \
|
||||
!= NULL) \
|
||||
name##_RB_SETCOLOR(oright, RB_BLACK);\
|
||||
name##_RB_SETCOLOR(tmp, RB_RED); \
|
||||
RB_ROTATE_LEFT(name, head, tmp, oright, field);\
|
||||
tmp = RB_LEFT(parent, field); \
|
||||
} \
|
||||
name##_RB_SETCOLOR(tmp,(name##_RB_GETCOLOR(parent)));\
|
||||
name##_RB_SETCOLOR(parent, RB_BLACK); \
|
||||
if (RB_LEFT(tmp, field)) \
|
||||
name##_RB_SETCOLOR(RB_LEFT(tmp, field), RB_BLACK);\
|
||||
RB_ROTATE_RIGHT(name, head, parent, tmp, field);\
|
||||
elm = RB_ROOT(head); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
if (elm) \
|
||||
name##_RB_SETCOLOR(elm, RB_BLACK); \
|
||||
} \
|
||||
\
|
||||
struct type * \
|
||||
name##_RB_REMOVE(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *child, *parent, *old = elm; \
|
||||
int color; \
|
||||
if (RB_LEFT(elm, field) == NULL) \
|
||||
child = RB_RIGHT(elm, field); \
|
||||
else if (RB_RIGHT(elm, field) == NULL) \
|
||||
child = RB_LEFT(elm, field); \
|
||||
else { \
|
||||
struct type *left; \
|
||||
elm = RB_RIGHT(elm, field); \
|
||||
while ((left = RB_LEFT(elm, field)) != NULL) \
|
||||
elm = left; \
|
||||
child = RB_RIGHT(elm, field); \
|
||||
parent = name##_RB_GETPARENT(elm); \
|
||||
color = name##_RB_GETCOLOR(elm); \
|
||||
if (child) \
|
||||
name##_RB_SETPARENT(child, parent); \
|
||||
if (parent) { \
|
||||
if (RB_LEFT(parent, field) == elm) \
|
||||
RB_LEFT(parent, field) = child; \
|
||||
else \
|
||||
RB_RIGHT(parent, field) = child; \
|
||||
RB_AUGMENT(parent); \
|
||||
} else \
|
||||
RB_ROOT(head) = child; \
|
||||
if (name##_RB_GETPARENT(elm) == old) \
|
||||
parent = elm; \
|
||||
(elm)->field = (old)->field; \
|
||||
if (name##_RB_GETPARENT(old)) { \
|
||||
if (RB_LEFT(name##_RB_GETPARENT(old), field) == old)\
|
||||
RB_LEFT(name##_RB_GETPARENT(old), field) = elm;\
|
||||
else \
|
||||
RB_RIGHT(name##_RB_GETPARENT(old), field) = elm;\
|
||||
RB_AUGMENT(name##_RB_GETPARENT(old)); \
|
||||
} else \
|
||||
RB_ROOT(head) = elm; \
|
||||
name##_RB_SETPARENT(RB_LEFT(old, field), elm); \
|
||||
if (RB_RIGHT(old, field)) \
|
||||
name##_RB_SETPARENT(RB_RIGHT(old, field), elm); \
|
||||
if (parent) { \
|
||||
left = parent; \
|
||||
do { \
|
||||
RB_AUGMENT(left); \
|
||||
} while ((left = name##_RB_GETPARENT(left)) != NULL); \
|
||||
} \
|
||||
goto color; \
|
||||
} \
|
||||
parent = name##_RB_GETPARENT(elm); \
|
||||
color = name##_RB_GETCOLOR(elm); \
|
||||
if (child) \
|
||||
name##_RB_SETPARENT(child, parent); \
|
||||
if (parent) { \
|
||||
if (RB_LEFT(parent, field) == elm) \
|
||||
RB_LEFT(parent, field) = child; \
|
||||
else \
|
||||
RB_RIGHT(parent, field) = child; \
|
||||
RB_AUGMENT(parent); \
|
||||
} else \
|
||||
RB_ROOT(head) = child; \
|
||||
color: \
|
||||
if (color == RB_BLACK) \
|
||||
name##_RB_REMOVE_COLOR(head, parent, child); \
|
||||
return (old); \
|
||||
} \
|
||||
\
|
||||
/* Inserts a node into the RB tree */ \
|
||||
struct type * \
|
||||
name##_RB_INSERT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp; \
|
||||
struct type *parent = NULL; \
|
||||
int comp = 0; \
|
||||
tmp = RB_ROOT(head); \
|
||||
while (tmp) { \
|
||||
parent = tmp; \
|
||||
comp = (cmp)(elm, parent); \
|
||||
if (comp < 0) \
|
||||
tmp = RB_LEFT(tmp, field); \
|
||||
else if (comp > 0) \
|
||||
tmp = RB_RIGHT(tmp, field); \
|
||||
else \
|
||||
return (tmp); \
|
||||
} \
|
||||
RB_SET(name, elm, parent, field); \
|
||||
if (parent != NULL) { \
|
||||
if (comp < 0) \
|
||||
RB_LEFT(parent, field) = elm; \
|
||||
else \
|
||||
RB_RIGHT(parent, field) = elm; \
|
||||
RB_AUGMENT(parent); \
|
||||
} else \
|
||||
RB_ROOT(head) = elm; \
|
||||
name##_RB_INSERT_COLOR(head, elm); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
/* Finds the node with the same key as elm */ \
|
||||
struct type * \
|
||||
name##_RB_FIND(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp = RB_ROOT(head); \
|
||||
int comp; \
|
||||
while (tmp) { \
|
||||
comp = cmp(elm, tmp); \
|
||||
if (comp < 0) \
|
||||
tmp = RB_LEFT(tmp, field); \
|
||||
else if (comp > 0) \
|
||||
tmp = RB_RIGHT(tmp, field); \
|
||||
else \
|
||||
return (tmp); \
|
||||
} \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
/* ARGSUSED */ \
|
||||
struct type * \
|
||||
name##_RB_NEXT(struct type *elm) \
|
||||
{ \
|
||||
if (RB_RIGHT(elm, field)) { \
|
||||
elm = RB_RIGHT(elm, field); \
|
||||
while (RB_LEFT(elm, field)) \
|
||||
elm = RB_LEFT(elm, field); \
|
||||
} else { \
|
||||
if (name##_RB_GETPARENT(elm) && \
|
||||
(elm == RB_LEFT(name##_RB_GETPARENT(elm), field))) \
|
||||
elm = name##_RB_GETPARENT(elm); \
|
||||
else { \
|
||||
while (name##_RB_GETPARENT(elm) && \
|
||||
(elm == RB_RIGHT(name##_RB_GETPARENT(elm), field)))\
|
||||
elm = name##_RB_GETPARENT(elm); \
|
||||
elm = name##_RB_GETPARENT(elm); \
|
||||
} \
|
||||
} \
|
||||
return (elm); \
|
||||
} \
|
||||
\
|
||||
struct type * \
|
||||
name##_RB_MINMAX(struct name *head, int val) \
|
||||
{ \
|
||||
struct type *tmp = RB_ROOT(head); \
|
||||
struct type *parent = NULL; \
|
||||
while (tmp) { \
|
||||
parent = tmp; \
|
||||
if (val < 0) \
|
||||
tmp = RB_LEFT(tmp, field); \
|
||||
else \
|
||||
tmp = RB_RIGHT(tmp, field); \
|
||||
} \
|
||||
return (parent); \
|
||||
}
|
||||
|
||||
|
||||
#define RB_PROTOTYPE_PREV(name, type, field, cmp) \
|
||||
RB_PROTOTYPE(name, type, field, cmp) \
|
||||
struct type *name##_RB_PREV(struct type *);
|
||||
|
||||
|
||||
#define RB_PROTOTYPE_SC_PREV(_sc_, name, type, field, cmp) \
|
||||
RB_PROTOTYPE_SC(_sc_, name, type, field, cmp) \
|
||||
_sc_ struct type *name##_RB_PREV(struct type *);
|
||||
|
||||
#define RB_GENERATE_PREV(name, type, field, cmp) \
|
||||
RB_GENERATE(name, type, field, cmp) \
|
||||
struct type * \
|
||||
name##_RB_PREV(struct type *elm) \
|
||||
{ \
|
||||
if (RB_LEFT(elm, field)) { \
|
||||
elm = RB_LEFT(elm, field); \
|
||||
while (RB_RIGHT(elm, field)) \
|
||||
elm = RB_RIGHT(elm, field); \
|
||||
} else { \
|
||||
if (name##_RB_GETPARENT(elm) && \
|
||||
(elm == RB_RIGHT(name##_RB_GETPARENT(elm), field))) \
|
||||
elm = name##_RB_GETPARENT(elm); \
|
||||
else { \
|
||||
while (name##_RB_GETPARENT(elm) && \
|
||||
(elm == RB_LEFT(name##_RB_GETPARENT(elm), field)))\
|
||||
elm = name##_RB_GETPARENT(elm); \
|
||||
elm = name##_RB_GETPARENT(elm); \
|
||||
} \
|
||||
} \
|
||||
return (elm); \
|
||||
} \
|
||||
|
||||
#define RB_NEGINF -1
|
||||
#define RB_INF 1
|
||||
|
||||
#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
|
||||
#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
|
||||
#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
|
||||
#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
|
||||
#define RB_PREV(name, x, y) name##_RB_PREV(y)
|
||||
#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
|
||||
#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
|
||||
|
||||
#define RB_FOREACH(x, name, head) \
|
||||
for ((x) = RB_MIN(name, head); \
|
||||
(x) != NULL; \
|
||||
(x) = name##_RB_NEXT(x))
|
||||
|
||||
#define RB_FOREACH_FROM(x, name, y) \
|
||||
for ((x) = (y); \
|
||||
((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
|
||||
(x) = (y))
|
||||
|
||||
#define RB_FOREACH_REVERSE_FROM(x, name, y) \
|
||||
for ((x) = (y); \
|
||||
((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
|
||||
(x) = (y))
|
||||
|
||||
#define RB_FOREACH_SAFE(x, name, head, y) \
|
||||
for ((x) = RB_MIN(name, head); \
|
||||
((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
|
||||
(x) = (y))
|
||||
|
||||
#endif /* _LIBKERN_TREE_H_ */
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2008 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. The rights granted to you under the License
|
||||
* may not be used to create, or enable the creation or redistribution of,
|
||||
* unlawful or unlicensed copies of an Apple operating system, or to
|
||||
* circumvent, violate, or enable the circumvention or violation of, any
|
||||
* terms of an Apple operating system software license agreement.
|
||||
*
|
||||
* Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)radix.h 8.2 (Berkeley) 10/31/94
|
||||
* $FreeBSD: src/sys/net/radix.h,v 1.16.2.1 2000/05/03 19:17:11 wollman Exp $
|
||||
*/
|
||||
|
||||
#ifndef _RADIX_H_
|
||||
#define _RADIX_H_
|
||||
#include <sys/appleapiopts.h>
|
||||
|
||||
#ifdef PRIVATE
|
||||
|
||||
#ifdef MALLOC_DECLARE
|
||||
MALLOC_DECLARE(M_RTABLE);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Radix search tree node layout.
|
||||
*/
|
||||
|
||||
struct radix_node {
|
||||
struct radix_mask *rn_mklist; /* list of masks contained in subtree */
|
||||
struct radix_node *rn_parent; /* parent */
|
||||
short rn_bit; /* bit offset; -1-index(netmask) */
|
||||
char rn_bmask; /* node: mask for bit test*/
|
||||
u_char rn_flags; /* enumerated next */
|
||||
#define RNF_NORMAL 1 /* leaf contains normal route */
|
||||
#define RNF_ROOT 2 /* leaf is root leaf for tree */
|
||||
#define RNF_ACTIVE 4 /* This node is alive (for rtfree) */
|
||||
union {
|
||||
struct { /* leaf only data: */
|
||||
caddr_t rn_Key; /* object of search */
|
||||
caddr_t rn_Mask; /* netmask, if present */
|
||||
struct radix_node *rn_Dupedkey;
|
||||
} rn_leaf;
|
||||
struct { /* node only data: */
|
||||
int rn_Off; /* where to start compare */
|
||||
struct radix_node *rn_L;/* progeny */
|
||||
struct radix_node *rn_R;/* progeny */
|
||||
} rn_node;
|
||||
} rn_u;
|
||||
#ifdef RN_DEBUG
|
||||
int rn_info;
|
||||
struct radix_node *rn_twin;
|
||||
struct radix_node *rn_ybro;
|
||||
#endif
|
||||
|
||||
#if __arm__ && (__BIGGEST_ALIGNMENT__ > 4)
|
||||
/* For the newer ARMv7k ABI where 64-bit types are 64-bit aligned, but pointers
|
||||
* are 32-bit:
|
||||
* Aligned to 64-bit since this is cast to rtentry, which is 64-bit aligned.
|
||||
*/
|
||||
} __attribute__ ((aligned(8)));
|
||||
#else
|
||||
};
|
||||
#endif
|
||||
|
||||
#define rn_dupedkey rn_u.rn_leaf.rn_Dupedkey
|
||||
#define rn_key rn_u.rn_leaf.rn_Key
|
||||
#define rn_mask rn_u.rn_leaf.rn_Mask
|
||||
#define rn_offset rn_u.rn_node.rn_Off
|
||||
#define rn_left rn_u.rn_node.rn_L
|
||||
#define rn_right rn_u.rn_node.rn_R
|
||||
|
||||
/*
|
||||
* Annotations to tree concerning potential routes applying to subtrees.
|
||||
*/
|
||||
|
||||
struct radix_mask {
|
||||
short rm_bit; /* bit offset; -1-index(netmask) */
|
||||
char rm_unused; /* cf. rn_bmask */
|
||||
u_char rm_flags; /* cf. rn_flags */
|
||||
struct radix_mask *rm_mklist; /* more masks to try */
|
||||
union {
|
||||
caddr_t rmu_mask; /* the mask */
|
||||
struct radix_node *rmu_leaf; /* for normal routes */
|
||||
} rm_rmu;
|
||||
int rm_refs; /* # of references to this struct */
|
||||
};
|
||||
|
||||
#define rm_mask rm_rmu.rmu_mask
|
||||
#define rm_leaf rm_rmu.rmu_leaf /* extra field would make 32 bytes */
|
||||
|
||||
|
||||
#define MKGet(m) {\
|
||||
if (rn_mkfreelist) {\
|
||||
m = rn_mkfreelist; \
|
||||
rn_mkfreelist = (m)->rm_mklist; \
|
||||
} else \
|
||||
R_Malloc(m, struct radix_mask *, sizeof (*(m))); }\
|
||||
|
||||
#define MKFree(m) { (m)->rm_mklist = rn_mkfreelist; rn_mkfreelist = (m);}
|
||||
|
||||
typedef int walktree_f_t(struct radix_node *, void *);
|
||||
typedef int rn_matchf_t(struct radix_node *, void *);
|
||||
|
||||
struct radix_node_head {
|
||||
struct radix_node *rnh_treetop;
|
||||
int rnh_addrsize; /* permit, but not require fixed keys */
|
||||
int rnh_pktsize; /* permit, but not require fixed keys */
|
||||
struct radix_node *(*rnh_addaddr) /* add based on sockaddr */
|
||||
(void *v, void *mask,
|
||||
struct radix_node_head *head, struct radix_node nodes[]);
|
||||
struct radix_node *(*rnh_addpkt) /* add based on packet hdr */
|
||||
(void *v, void *mask,
|
||||
struct radix_node_head *head, struct radix_node nodes[]);
|
||||
struct radix_node *(*rnh_deladdr) /* remove based on sockaddr */
|
||||
(void *v, void *mask, struct radix_node_head *head);
|
||||
struct radix_node *(*rnh_delpkt) /* remove based on packet hdr */
|
||||
(void *v, void *mask, struct radix_node_head *head);
|
||||
struct radix_node *(*rnh_matchaddr) /* locate based on sockaddr */
|
||||
(void *v, struct radix_node_head *head);
|
||||
/* locate based on sockaddr and rn_matchf_t() */
|
||||
struct radix_node *(*rnh_matchaddr_args)
|
||||
(void *v, struct radix_node_head *head,
|
||||
rn_matchf_t *f, void *w);
|
||||
struct radix_node *(*rnh_lookup) /* locate based on sockaddr */
|
||||
(void *v, void *mask, struct radix_node_head *head);
|
||||
/* locate based on sockaddr, mask and rn_matchf_t() */
|
||||
struct radix_node *(*rnh_lookup_args)
|
||||
(void *v, void *mask, struct radix_node_head *head,
|
||||
rn_matchf_t *f, void *);
|
||||
struct radix_node *(*rnh_matchpkt) /* locate based on packet hdr */
|
||||
(void *v, struct radix_node_head *head);
|
||||
int (*rnh_walktree) /* traverse tree */
|
||||
(struct radix_node_head *head, walktree_f_t *f, void *w);
|
||||
int (*rnh_walktree_from) /* traverse tree below a */
|
||||
(struct radix_node_head *head, void *a, void *m,
|
||||
walktree_f_t *f, void *w);
|
||||
void (*rnh_close) /* do something when the last ref drops */
|
||||
(struct radix_node *rn, struct radix_node_head *head);
|
||||
struct radix_node rnh_nodes[3]; /* empty tree for common case */
|
||||
int rnh_cnt; /* tree dimension */
|
||||
};
|
||||
|
||||
#ifndef KERNEL
|
||||
#define Bcmp(a, b, n) bcmp(((char *)(a)), ((char *)(b)), (n))
|
||||
#define Bcopy(a, b, n) bcopy(((char *)(a)), ((char *)(b)), (unsigned)(n))
|
||||
#define Bzero(p, n) bzero((char *)(p), (int)(n));
|
||||
#define R_Malloc(p, t, n) (p = (t) malloc((unsigned int)(n)))
|
||||
#define R_Free(p) free((char *)p);
|
||||
#else
|
||||
#define Bcmp(a, b, n) bcmp(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n))
|
||||
#define Bcopy(a, b, n) bcopy(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n))
|
||||
#define Bzero(p, n) bzero((caddr_t)(p), (unsigned)(n));
|
||||
#define R_Malloc(p, t, n) (p = (t) _MALLOC((uint32_t)(n), M_RTABLE, M_WAITOK))
|
||||
#define R_Free(p) FREE((caddr_t)p, M_RTABLE);
|
||||
#endif /*KERNEL*/
|
||||
|
||||
void rn_init(void);
|
||||
int rn_inithead(void **, int);
|
||||
int rn_refines(void *, void *);
|
||||
struct radix_node
|
||||
*rn_addmask(void *, int, int),
|
||||
*rn_addroute(void *, void *, struct radix_node_head *,
|
||||
struct radix_node [2]),
|
||||
*rn_delete(void *, void *, struct radix_node_head *),
|
||||
*rn_lookup(void *v_arg, void *m_arg, struct radix_node_head *head),
|
||||
*rn_lookup_args(void *v_arg, void *m_arg, struct radix_node_head *head,
|
||||
rn_matchf_t *, void *),
|
||||
*rn_match(void *, struct radix_node_head *),
|
||||
*rn_match_args(void *, struct radix_node_head *, rn_matchf_t *, void *);
|
||||
|
||||
#endif /* PRIVATE */
|
||||
#endif /* _RADIX_H_ */
|
Loading…
Reference in New Issue