├── stamp-h.in ├── print.h ├── hash.h ├── mysignal.h ├── acconfig.h ├── pcaputil.h ├── ares.h ├── osstack.h ├── README ├── ndb.h ├── parse.h ├── hash.c ├── mysignal.c ├── bag.h ├── config ├── mkinstalldirs ├── install-sh └── missing ├── Makefile.am ├── dscan.h ├── print.c ├── LICENSE ├── ahost.c ├── dscan-int.h ├── pcaputil.c ├── config.h.in ├── dscan.8 ├── compat ├── strsep.c └── sys │ ├── queue.h │ └── tree.h ├── bag-test.c ├── osstack.c ├── acinclude.m4 ├── parse.c ├── main.c ├── configure.ac ├── ndb.c ├── recv.c ├── bag.c ├── dscan.c ├── scan.c ├── ares.c ├── aclocal.m4 └── Makefile.in /stamp-h.in: -------------------------------------------------------------------------------- 1 | timestamp 2 | -------------------------------------------------------------------------------- /print.h: -------------------------------------------------------------------------------- 1 | /* 2 | * print.h 3 | * 4 | * Copyright (c) 2002 Dug Song 5 | * 6 | * $Id: print.h,v 1.2 2002/11/22 04:42:35 dugsong Exp $ 7 | */ 8 | 9 | #ifndef PRINT_H 10 | #define PRINT_H 11 | 12 | char *print_duration(float seconds); 13 | char *print_bitrate(float bitrate); 14 | 15 | #endif /* PRINT_H */ 16 | -------------------------------------------------------------------------------- /hash.h: -------------------------------------------------------------------------------- 1 | /* 2 | * hash.h 3 | * 4 | * Copyright (c) 2002 Dug Song 5 | * 6 | * $Id: hash.h,v 1.3 2002/12/10 05:45:05 dugsong Exp $ 7 | */ 8 | 9 | #ifndef HASH_H 10 | #define HASH_H 11 | 12 | void hash_init(uint32_t *h); 13 | void hash_update(uint32_t *h, const void *buf, int len); 14 | 15 | #endif /* HASH_H */ 16 | -------------------------------------------------------------------------------- /mysignal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * mysignal.h 3 | * 4 | * Copyright (c) 2002 Dug Song 5 | * 6 | * $Id: mysignal.h,v 1.2 2002/11/22 04:42:34 dugsong Exp $ 7 | */ 8 | 9 | #ifndef MYSIGNAL_H 10 | #define MYSIGNAL_H 11 | 12 | #include 13 | 14 | void mysignal(int sig, void (*act)(int)); 15 | 16 | #endif /* MYSIGNAL_H */ 17 | -------------------------------------------------------------------------------- /acconfig.h: -------------------------------------------------------------------------------- 1 | @BOTTOM@ 2 | 3 | /* XXX - for strl* definitions below */ 4 | #include 5 | 6 | #ifdef HAVE_INTTYPES_H 7 | #include 8 | #endif 9 | 10 | #ifndef HAVE_STRLCPY 11 | size_t strlcpy(char *, const char *, size_t); 12 | #endif 13 | 14 | #ifndef HAVE_STRSEP 15 | char *strsep(char **stringp, const char *delim); 16 | #endif 17 | -------------------------------------------------------------------------------- /pcaputil.h: -------------------------------------------------------------------------------- 1 | /* 2 | * pcaputil.h 3 | * 4 | * Copyright (c) 2001 Dug Song 5 | * 6 | * $Id: pcaputil.h,v 1.1.1.1 2002/10/09 06:59:20 dugsong Exp $ 7 | */ 8 | 9 | #ifndef PCAPUTIL_H 10 | #define PCAPUTIL_H 11 | 12 | pcap_t *pcap_open(char *name, int promisc, int snaplen); 13 | int pcap_dloff(pcap_t *pcap); 14 | int pcap_filter(pcap_t *pcap, const char *fmt, ...); 15 | 16 | #endif /* PCAPUTIL_H */ 17 | -------------------------------------------------------------------------------- /ares.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ares.h 3 | * 4 | * Copyright (c) 2002 Dug Song 5 | * 6 | * $Id: ares.h,v 1.2 2002/11/20 16:00:49 dugsong Exp $ 7 | */ 8 | 9 | #ifndef ARES_H 10 | #define ARES_H 11 | 12 | typedef void (*ares_callback)(uint32_t ip, const char *hostname, void *arg); 13 | 14 | int ares_open(void); 15 | int ares_query(uint32_t ip, ares_callback callback, void *arg); 16 | void ares_close(void); 17 | 18 | #endif /* ARES_H */ 19 | -------------------------------------------------------------------------------- /osstack.h: -------------------------------------------------------------------------------- 1 | /* 2 | * osstack.h 3 | * 4 | * Copyright (c) 2002 Dug Song 5 | * 6 | * $Id: osstack.h,v 1.3 2002/11/22 04:42:35 dugsong Exp $ 7 | */ 8 | 9 | #ifndef OSSTACK_H 10 | #define OSSTACK_H 11 | 12 | typedef struct osstack osstack_t; 13 | 14 | osstack_t *osstack_open(const char *os); 15 | int osstack_syn_rewrite(osstack_t *o, void *pkt, int size); 16 | osstack_t *osstack_close(osstack_t *o); 17 | 18 | #endif /* OSSTACK_H */ 19 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | 2 | i once needed this, but didn't want to release it. now it doesn't 3 | matter. hope some of the code can be useful to the right people. 4 | 5 | you will need a lot of large listening routes, and fast scan sources 6 | (e.g. at a major IX) not subject to upstream uRPF. the point was to 7 | reduce the temporal / spatial locality of sources / targets in a scan. 8 | 9 | yes, the scans are lossy. this wasn't built for accuracy, but for 10 | large scale results. 11 | 12 | -d. 13 | -------------------------------------------------------------------------------- /ndb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ndb.h 3 | * 4 | * Copyright (c) 2002 Dug Song 5 | * 6 | * $Id: ndb.h,v 1.2 2002/11/22 04:42:34 dugsong Exp $ 7 | */ 8 | 9 | #ifndef NDB_H 10 | #define NDB_H 11 | 12 | void ndb_open(const char *dirpath); 13 | 14 | char *ndb_serv_name(int proto, int port); 15 | int ndb_serv_num(int proto, const char *name); 16 | 17 | char *ndb_proto_name(int proto); 18 | int ndb_proto_num(const char *name); 19 | 20 | void ndb_close(void); 21 | 22 | #endif /* NDB_H */ 23 | -------------------------------------------------------------------------------- /parse.h: -------------------------------------------------------------------------------- 1 | /* 2 | * parse.h 3 | * 4 | * Copyright (c) 2002 Dug Song 5 | * 6 | * $Id: parse.h,v 1.2 2002/11/22 04:42:35 dugsong Exp $ 7 | */ 8 | 9 | #ifndef PARSE_H 10 | #define PARSE_H 11 | 12 | int parse_host_range(const char *p, uint32_t *start, uint32_t *end); 13 | int parse_port_range(const char *p, uint32_t *start, uint32_t *end); 14 | int parse_proto_range(const char *p, uint32_t *start, uint32_t *end); 15 | int parse_num_range(const char *p, uint32_t *start, uint32_t *end); 16 | 17 | #endif /* PARSE_H */ 18 | -------------------------------------------------------------------------------- /hash.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hash.c 3 | * 4 | * Copyright (c) 2002 Dug Song 5 | * 6 | * $Id: hash.c,v 1.4 2002/12/10 05:45:05 dugsong Exp $ 7 | */ 8 | 9 | #ifdef HAVE_CONFIG_H 10 | # include "config.h" 11 | #endif 12 | 13 | #include "hash.h" 14 | 15 | /* Public domain Fowler/Noll/Vo hash. */ 16 | 17 | #define FNV_32_PRIME ((uint32_t)0x01000193) 18 | #define FNV1_32_INIT ((uint32_t)0x811c9dc5) 19 | 20 | void 21 | hash_init(uint32_t *hash) 22 | { 23 | *hash = FNV1_32_INIT; 24 | } 25 | 26 | void 27 | hash_update(uint32_t *hash, const void *buf, int len) 28 | { 29 | u_char *p, *end; 30 | 31 | for (p = (u_char *)buf, end = (u_char *)buf + len; p < end; p++) { 32 | *hash *= FNV_32_PRIME; 33 | *hash ^= (uint32_t)*p; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /mysignal.c: -------------------------------------------------------------------------------- 1 | /* 2 | * mysignal.c 3 | * 4 | * Copyright (c) 2002 Dug Song 5 | * 6 | * $Id: mysignal.c,v 1.3 2002/11/22 04:42:34 dugsong Exp $ 7 | */ 8 | 9 | #ifdef HAVE_CONFIG_H 10 | # include "config.h" 11 | #endif 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include "mysignal.h" 18 | 19 | void 20 | mysignal(int sig, void (*act)(int)) 21 | { 22 | #ifdef HAVE_SIGACTION 23 | struct sigaction sa, osa; 24 | 25 | sigaction(sig, NULL, &osa); 26 | 27 | if (osa.sa_handler != act) { 28 | memset(&sa, 0, sizeof(sa)); 29 | sigemptyset(&sa.sa_mask); 30 | sa.sa_flags = 0; 31 | #if defined(SA_INTERRUPT) 32 | if (sig == SIGALRM) 33 | sa.sa_flags |= SA_INTERRUPT; 34 | #endif 35 | sa.sa_handler = act; 36 | 37 | sigaction(sig, &sa, NULL); 38 | } 39 | #else 40 | signal(sig, act); 41 | #endif 42 | } 43 | -------------------------------------------------------------------------------- /bag.h: -------------------------------------------------------------------------------- 1 | /* 2 | * bag.h 3 | * 4 | * Copyright (c) 2002 Dug Song 5 | * 6 | * $Id: bag.h,v 1.2 2002/11/22 04:42:34 dugsong Exp $ 7 | */ 8 | 9 | #ifndef BAG_H 10 | #define BAG_H 11 | 12 | typedef struct bag bag_t; 13 | 14 | typedef int (*bag_handler)(uint32_t value, void *arg); 15 | 16 | bag_t *bag_open(void); 17 | 18 | int bag_add(bag_t *b, uint32_t value); 19 | int bag_add_range(bag_t *b, uint32_t start, uint32_t end); 20 | 21 | uint32_t bag_count(bag_t *b); 22 | uint32_t bag_left(bag_t *b); 23 | 24 | int bag_shuffle(bag_t *b, rand_t *rnd); 25 | 26 | int bag_first(bag_t *b, uint32_t *first); 27 | int bag_last(bag_t *b, uint32_t *last); 28 | int bag_iter(bag_t *b, uint32_t *value); 29 | int bag_loop(bag_t *b, bag_handler callback, void *arg); 30 | 31 | int bag_refill(bag_t *b); 32 | 33 | bag_t *bag_close(bag_t *b); 34 | 35 | #endif /* BAG_H */ 36 | -------------------------------------------------------------------------------- /config/mkinstalldirs: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # mkinstalldirs --- make directory hierarchy 3 | # Author: Noah Friedman 4 | # Created: 1993-05-16 5 | # Public domain 6 | 7 | # $Id: mkinstalldirs,v 1.1 2002/11/21 06:37:26 dugsong Exp $ 8 | 9 | errstatus=0 10 | 11 | for file 12 | do 13 | set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` 14 | shift 15 | 16 | pathcomp= 17 | for d 18 | do 19 | pathcomp="$pathcomp$d" 20 | case "$pathcomp" in 21 | -* ) pathcomp=./$pathcomp ;; 22 | esac 23 | 24 | if test ! -d "$pathcomp"; then 25 | echo "mkdir $pathcomp" 26 | 27 | mkdir "$pathcomp" || lasterr=$? 28 | 29 | if test ! -d "$pathcomp"; then 30 | errstatus=$lasterr 31 | fi 32 | fi 33 | 34 | pathcomp="$pathcomp/" 35 | done 36 | done 37 | 38 | exit $errstatus 39 | 40 | # mkinstalldirs ends here 41 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | ## $Id: Makefile.am,v 1.5 2002/12/04 01:54:11 dugsong Exp $ 2 | 3 | AUTOMAKE_OPTIONS = foreign no-dependencies 4 | 5 | INCLUDES = @PCAPINC@ @EVENTINC@ @DNETINC@ -I$(top_srcdir)/compat 6 | 7 | LDADD = @LIBOBJS@ @PCAPLIB@ @EVENTLIB@ @DNETLIB@ 8 | 9 | sbin_PROGRAMS = dscan 10 | 11 | dscan_SOURCES = ares.c ares.h bag.c bag.h dscan-int.h dscan.c dscan.h hash.c \ 12 | hash.h main.c mysignal.c mysignal.h ndb.c ndb.h osstack.c osstack.h \ 13 | parse.c parse.h pcaputil.c pcaputil.h print.c print.h recv.c scan.c 14 | 15 | man_MANS = dscan.8 16 | 17 | dscan.8.txt: dscan.8 18 | groff -t -e -man -Tascii dscan.8 | col -bx > $@ 19 | 20 | strsep.o: $(top_srcdir)/compat/strsep.c 21 | $(COMPILE) -c $< 22 | 23 | ahost: ahost.o ares.o bag.o parse.o 24 | $(LINK) ahost.o ares.o bag.o parse.o $(LDADD) 25 | 26 | bag-test: bag-test.o bag.o parse.o 27 | $(LINK) bag-test.o bag.o parse.o $(LDADD) -ledit -ltermcap 28 | 29 | EXTRA_DIST = LICENSE config/install-sh config/missing config/mkinstalldirs \ 30 | compat/strsep.c compat/sys/queue.h compat/sys/tree.h \ 31 | ahost.c bag-test.c $(man_MANS) 32 | 33 | DISTCLEANFILES = *~ 34 | 35 | -------------------------------------------------------------------------------- /dscan.h: -------------------------------------------------------------------------------- 1 | /* 2 | * dscan.h 3 | * 4 | * Copyright (c) 2002 Dug Song 5 | * 6 | * $Id: dscan.h,v 1.6 2002/12/10 05:45:05 dugsong Exp $ 7 | */ 8 | 9 | #ifndef DSCAN_H 10 | #define DSCAN_H 11 | 12 | #define DSCAN_RECV (1 << 0) 13 | #define DSCAN_TCP (1 << 1) 14 | #define DSCAN_PING (1 << 2) 15 | 16 | #define DSCAN_RECV_TIMEOUT 3 17 | 18 | typedef struct dscan_ctx dscan_t; 19 | 20 | dscan_t *dscan_open(void); 21 | 22 | int dscan_set_mode(dscan_t *ctx, uint32_t mode); 23 | 24 | int dscan_set_key(dscan_t *ctx, const char *key); 25 | int dscan_set_resolv(dscan_t *ctx, int use_dns); 26 | int dscan_set_dsts(dscan_t *ctx, const char *dsts); 27 | int dscan_set_cache(dscan_t *ctx, int cachesz); 28 | 29 | int dscan_set_input(dscan_t *ctx, FILE *fp); 30 | int dscan_set_bitrate(dscan_t *ctx, const char *bitrate); 31 | int dscan_set_osstack(dscan_t *ctx, const char *os); 32 | int dscan_set_random(dscan_t *ctx, int use_rand); 33 | int dscan_set_srcs(dscan_t *ctx, const char *srcs); 34 | int dscan_set_tcpflags(dscan_t *ctx, const char *tcpflags); 35 | int dscan_set_ports(dscan_t *ctx, const char *ports); 36 | 37 | void dscan_scan(dscan_t *ctx); 38 | void dscan_recv(dscan_t *ctx); 39 | 40 | dscan_t *dscan_close(dscan_t *ctx); 41 | 42 | #endif /* DSCAN_H */ 43 | -------------------------------------------------------------------------------- /print.c: -------------------------------------------------------------------------------- 1 | /* 2 | * print.c 3 | * 4 | * Copyright (c) 2002 Dug Song 5 | * 6 | * $Id: print.c,v 1.3 2002/12/10 05:45:05 dugsong Exp $ 7 | */ 8 | 9 | #ifdef HAVE_CONFIG_H 10 | # include "config.h" 11 | #endif 12 | 13 | #include 14 | #include 15 | 16 | #include "print.h" 17 | 18 | #define MIN (60) 19 | #define HOUR (MIN * 60) 20 | #define DAY (HOUR * 24) 21 | #define WEEK (DAY * 7) 22 | 23 | char * 24 | print_duration(float seconds) 25 | { 26 | static char buf[32]; 27 | 28 | if (seconds > WEEK) 29 | snprintf(buf, sizeof(buf), "%.1f weeks", seconds / WEEK); 30 | else if (seconds > DAY) 31 | snprintf(buf, sizeof(buf), "%.1f days", seconds / DAY); 32 | else if (seconds > HOUR) 33 | snprintf(buf, sizeof(buf), "%.1f hours", seconds / HOUR); 34 | else if (seconds > MIN) 35 | snprintf(buf, sizeof(buf), "%.1f minutes", seconds / MIN); 36 | else 37 | snprintf(buf, sizeof(buf), "%.1f seconds", seconds); 38 | 39 | return (buf); 40 | } 41 | 42 | #define KBPS (1000) 43 | #define MBPS (KBPS * 1000) 44 | #define GBPS (MBPS * 1000) 45 | 46 | char * 47 | print_bitrate(float bitrate) 48 | { 49 | static char buf[32]; 50 | 51 | if (bitrate > GBPS) 52 | snprintf(buf, sizeof(buf), "%.1f Gbps", bitrate / GBPS); 53 | else if (bitrate > MBPS) 54 | snprintf(buf, sizeof(buf), "%.1f Mbps", bitrate / MBPS); 55 | else if (bitrate > KBPS) 56 | snprintf(buf, sizeof(buf), "%.1f Kbps", bitrate / KBPS); 57 | else 58 | snprintf(buf, sizeof(buf), "%.1f bps", bitrate / MBPS); 59 | 60 | return (buf); 61 | } 62 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Copyright (c) 2002 Dug Song 3 | All rights reserved, all wrongs reversed. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions 7 | are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 2. Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 3. The names of the authors and copyright holders may not be used to 15 | endorse or promote products derived from this software without 16 | specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 19 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 20 | AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 | THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 24 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 27 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | -------------------------------------------------------------------------------- /ahost.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ahost.c 3 | * 4 | * Copyright (c) 2002 Dug Song 5 | * 6 | * $Id: ahost.c,v 1.2 2002/11/22 04:42:34 dugsong Exp $ 7 | */ 8 | 9 | #ifdef HAVE_CONFIG_H 10 | # include "config.h" 11 | #endif 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | 21 | #include "ares.h" 22 | #include "bag.h" 23 | #include "parse.h" 24 | 25 | static void 26 | usage(void) 27 | { 28 | fprintf(stderr, "Usage: ahost [host/net ...]\n"); 29 | exit(1); 30 | } 31 | 32 | static void 33 | print_dns(uint32_t ip, const char *hostname, void *arg) 34 | { 35 | if (hostname == NULL) 36 | hostname = "ERROR"; 37 | else if (*hostname == '\0') 38 | hostname = "unknown"; 39 | 40 | printf("%s (%s)\n", ip_ntoa(&ip), hostname); 41 | } 42 | 43 | static int 44 | query_ip(uint32_t ip, void *arg) 45 | { 46 | return (ares_query(htonl(ip), print_dns, NULL)); 47 | } 48 | 49 | int 50 | main(int argc, char *argv[]) 51 | { 52 | bag_t *bag; 53 | char buf[BUFSIZ]; 54 | uint32_t start, end; 55 | int c; 56 | 57 | bag = bag_open(); 58 | 59 | while ((c = getopt(argc, argv, "h?")) != -1) { 60 | switch (c) { 61 | default: 62 | usage(); 63 | break; 64 | } 65 | } 66 | argc -= optind; 67 | argv += optind; 68 | 69 | for (c = 0; c < argc; c++) { 70 | if (parse_host_range(argv[c], &start, &end) < 0) 71 | errx(1, "invalid host/net: %s", argv[c]); 72 | bag_add_range(bag, ntohl(start), ntohl(end)); 73 | } 74 | if (c == 0) { 75 | while (fgets(buf, sizeof(buf), stdin) != NULL) { 76 | strtok(buf, "\r\n"); 77 | if (parse_host_range(buf, &start, &end) < 0) 78 | errx(1, "invalid host/net: %s", buf); 79 | bag_add_range(bag, ntohl(start), ntohl(end)); 80 | } 81 | 82 | } 83 | event_init(); 84 | 85 | ares_open(); 86 | 87 | bag_loop(bag, query_ip, NULL); 88 | 89 | event_dispatch(); 90 | 91 | bag = bag_close(bag); 92 | 93 | exit(0); 94 | } 95 | -------------------------------------------------------------------------------- /dscan-int.h: -------------------------------------------------------------------------------- 1 | /* 2 | * dscan-int.h 3 | * 4 | * Copyright (c) 2002 Dug Song 5 | * 6 | * $Id: dscan-int.h,v 1.7 2002/12/10 05:45:05 dugsong Exp $ 7 | */ 8 | 9 | #ifndef DSCAN_INT_H 10 | #define DSCAN_INT_H 11 | 12 | struct dscan_dif { 13 | struct intf_entry ifent; /* interface info */ 14 | bag_t *dsts; /* dsts routed thru intf */ 15 | pcap_t *pcap; /* packet capture handle */ 16 | struct event ev; /* receive event */ 17 | struct dscan_ctx *ctx; /* XXX 1 event/pcap cb arg */ 18 | TAILQ_ENTRY(dscan_dif) next; 19 | }; 20 | 21 | struct dscan_ctx { 22 | /* Shared info */ 23 | uint32_t mode; /* scan mode */ 24 | intf_t *intf; /* interface handle */ 25 | rand_t *rnd; /* entropy handle */ 26 | uint32_t key; /* scan key */ 27 | int resolv; /* resolve IPs to hostnames */ 28 | int spipe[2]; /* self-pipe */ 29 | TAILQ_HEAD(, dscan_dif) difs; /* listening interfaces */ 30 | uint32_t *hcache; /* hash cache */ 31 | int hcache_sz; /* hash cache size */ 32 | float duration; /* scan duration */ 33 | 34 | /* Scan config */ 35 | FILE *input; /* input handle */ 36 | bag_t *srcs; /* sources to spoof */ 37 | uint8_t proto; /* scan protocol */ 38 | bag_t *ports; /* target ports / ICMP types */ 39 | uint8_t tcpflags; /* TCP flags */ 40 | osstack_t *osstack; /* OS personality */ 41 | int random; /* randomize scan order */ 42 | float bitrate; /* target bitrate */ 43 | uint32_t tick_usec; /* tick interval (usec) */ 44 | uint32_t tick_bytes; /* max bytes per tick */ 45 | 46 | /* Recv config */ 47 | struct timeval tv; /* response timeout */ 48 | struct event spipe_ev; /* self-pipe event */ 49 | }; 50 | 51 | struct dscan_pkt { 52 | union { 53 | struct ip_hdr ip; 54 | } pkt_n_hdr_u; 55 | union { 56 | struct tcp_hdr tcp; 57 | struct { 58 | struct icmp_hdr icmp; 59 | union icmp_msg icmp_msg; 60 | } pkt_icmp_u; 61 | } pkt_t_hdr_u; 62 | }; 63 | #define pkt_ip pkt_n_hdr_u.ip 64 | #define pkt_tcp pkt_t_hdr_u.tcp 65 | #define pkt_icmp pkt_t_hdr_u.pkt_icmp_u.icmp 66 | #define pkt_icmp_msg pkt_t_hdr_u.pkt_icmp_u.icmp_msg 67 | 68 | #endif /* DSCAN_INT_H */ 69 | -------------------------------------------------------------------------------- /pcaputil.c: -------------------------------------------------------------------------------- 1 | /* 2 | * pcaputil.c 3 | * 4 | * Copyright (c) 2000 Dug Song 5 | * 6 | * $Id: pcaputil.c,v 1.2 2002/11/22 04:42:35 dugsong Exp $ 7 | */ 8 | 9 | #ifndef WIN32 10 | #include 11 | #include 12 | #include 13 | #include 14 | #endif 15 | 16 | #include 17 | #ifdef notyet 18 | # include 19 | #endif 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "pcaputil.h" 27 | 28 | pcap_t * 29 | pcap_open(char *name, int promisc, int snaplen) 30 | { 31 | struct stat st; 32 | char ebuf[PCAP_ERRBUF_SIZE]; 33 | pcap_t *pcap; 34 | 35 | if (name == NULL) { 36 | if ((name = pcap_lookupdev(ebuf)) == NULL) 37 | return (NULL); 38 | } else if (lstat(name, &st) == 0) { 39 | return (pcap_open_offline(name, ebuf)); 40 | } 41 | if ((pcap = pcap_open_live(name, snaplen, promisc, 10, ebuf)) == NULL) 42 | return (NULL); 43 | #if 0 44 | { 45 | int n = 1; 46 | 47 | if (ioctl(pcap_fileno(pcap), BIOCIMMEDIATE, &n) < 0) { 48 | pcap_close(pcap); 49 | return (NULL); 50 | } 51 | } 52 | #endif 53 | return (pcap); 54 | } 55 | 56 | int 57 | pcap_dloff(pcap_t *pd) 58 | { 59 | int i; 60 | 61 | i = pcap_datalink(pd); 62 | 63 | switch (i) { 64 | case DLT_EN10MB: 65 | i = 14; 66 | break; 67 | case DLT_IEEE802: 68 | i = 22; 69 | break; 70 | case DLT_FDDI: 71 | i = 21; 72 | break; 73 | #ifdef DLT_LOOP 74 | case DLT_LOOP: 75 | #endif 76 | case DLT_NULL: 77 | i = 4; 78 | break; 79 | default: 80 | i = -1; 81 | break; 82 | } 83 | return (i); 84 | } 85 | 86 | int 87 | pcap_filter(pcap_t *pcap, const char *fmt, ...) 88 | { 89 | struct bpf_program fcode; 90 | char buf[BUFSIZ]; 91 | va_list ap; 92 | 93 | va_start(ap, fmt); 94 | vsnprintf(buf, sizeof(buf), fmt, ap); 95 | va_end(ap); 96 | #ifdef notyet 97 | pcap_freecode(&pcap->fcode); 98 | #endif 99 | if (pcap_compile(pcap, &fcode, buf, 1, 0) < 0) 100 | return (-1); 101 | 102 | if (pcap_setfilter(pcap, &fcode) == -1) 103 | return (-1); 104 | 105 | return (0); 106 | } 107 | -------------------------------------------------------------------------------- /config.h.in: -------------------------------------------------------------------------------- 1 | /* config.h.in. Generated automatically from configure.ac by autoheader. */ 2 | 3 | /* Define if you have the `clock_getres' function. */ 4 | #undef HAVE_CLOCK_GETRES 5 | 6 | /* Define if you have the header file. */ 7 | #undef HAVE_INTTYPES_H 8 | 9 | /* Define if you have the `nsl' library (-lnsl). */ 10 | #undef HAVE_LIBNSL 11 | 12 | /* Define if you have the `resolv' library (-lresolv). */ 13 | #undef HAVE_LIBRESOLV 14 | 15 | /* Define if you have the `socket' library (-lsocket). */ 16 | #undef HAVE_LIBSOCKET 17 | 18 | /* Define if you have the `str' library (-lstr). */ 19 | #undef HAVE_LIBSTR 20 | 21 | /* Define if you have the header file. */ 22 | #undef HAVE_MEMORY_H 23 | 24 | /* Define if you have the `setproctitle' function. */ 25 | #undef HAVE_SETPROCTITLE 26 | 27 | /* Define if you have the `sigaction' function. */ 28 | #undef HAVE_SIGACTION 29 | 30 | /* Define if you have the header file. */ 31 | #undef HAVE_STDINT_H 32 | 33 | /* Define if you have the header file. */ 34 | #undef HAVE_STDLIB_H 35 | 36 | /* Define if you have the header file. */ 37 | #undef HAVE_STRINGS_H 38 | 39 | /* Define if you have the header file. */ 40 | #undef HAVE_STRING_H 41 | 42 | /* Define if you have the `strlcpy' function. */ 43 | #undef HAVE_STRLCPY 44 | 45 | /* Define if you have the `strsep' function. */ 46 | #undef HAVE_STRSEP 47 | 48 | /* Define if you have the header file. */ 49 | #undef HAVE_SYS_STAT_H 50 | 51 | /* Define if you have the header file. */ 52 | #undef HAVE_SYS_TYPES_H 53 | 54 | /* Define if you have that is POSIX.1 compatible. */ 55 | #undef HAVE_SYS_WAIT_H 56 | 57 | /* Define if you have the header file. */ 58 | #undef HAVE_UNISTD_H 59 | 60 | /* Name of package */ 61 | #undef PACKAGE 62 | 63 | /* Define if you have the ANSI C header files. */ 64 | #undef STDC_HEADERS 65 | 66 | /* Define if you can safely include both and . */ 67 | #undef TIME_WITH_SYS_TIME 68 | 69 | /* Version number of package */ 70 | #undef VERSION 71 | 72 | /* Define to empty if `const' does not conform to ANSI C. */ 73 | #undef const 74 | 75 | /* Define to `int' if does not define. */ 76 | #undef pid_t 77 | 78 | /* Define to `unsigned' if does not define. */ 79 | #undef size_t 80 | 81 | /* XXX - for strl* definitions below */ 82 | #include 83 | 84 | #ifdef HAVE_INTTYPES_H 85 | #include 86 | #endif 87 | 88 | #ifndef HAVE_STRLCPY 89 | size_t strlcpy(char *, const char *, size_t); 90 | #endif 91 | 92 | #ifndef HAVE_STRSEP 93 | char *strsep(char **stringp, const char *delim); 94 | #endif 95 | -------------------------------------------------------------------------------- /dscan.8: -------------------------------------------------------------------------------- 1 | .\" 2 | .\" Copyright (c) 2002 Dug Song 3 | .\" 4 | .\" $Id: dscan.8,v 1.1 2002/11/22 04:30:48 dugsong Exp $ 5 | .\" 6 | .TH DSCAN 8 7 | .SH NAME 8 | dscan \- fast, distributed TCP port scanner 9 | .SH SYNOPSIS 10 | \fBdscan\fR [\fB-lnr\fR] [\fB-b \fIbitrate\fR] [\fB-f \fIflags\fR] 11 | [\fB-k \fIkey\fR] [\fB-o \fIos\fR] 12 | .br 13 | [\fB-p \fIports\fR] [\fB-s \fIsrcs\fR] \fIdsts\fR 14 | .SH DESCRIPTION 15 | .B dscan 16 | is a fast TCP port scanner optimized for wide, distributed scans 17 | (e.g. of large networks, not individual hosts). 18 | .LP 19 | The options are as follows: 20 | .IP \fB-l\fR 21 | Listen-only mode. No scan packets will be sent -- only response packets 22 | matching a scan with the specified key will be displayed. 23 | .IP \fB-n\fR 24 | Disable hostname lookups. By default, asynchronous hostname lookups 25 | are enabled for responding hosts. 26 | .IP \fB-r\fR 27 | Perform a random walk of the target port and IP space, to evenly 28 | distribute scan packets among them (e.g. to avoid hammering each 29 | target in serial). 30 | .IP \fB-b \fIbitrate\fR 31 | Specify the bottleneck bandwidth to the target. The \fIbitrate\fR 32 | may be specified as Kbps, Mbps, or Gbps (e.g. "56k", "1M"). If the 33 | specified bitrate exceeds the actual bottleneck bandwidth, the scan 34 | will be lossy, and produce incomplete results. The default bitrate is 35 | 128Kbps. 36 | .IP \fB-f \fIflags\fR 37 | Specify TCP flags for each scan packet, as any combination of 38 | "SAFRPUWE", or "N" for no flags set. TCP SYN ("S") is enabled by 39 | default. 40 | .IP \fB-k \fIkey\fR 41 | Specify a secret key for this scan. In a distributed scan where the 42 | scanning hosts spoof the source address of the receiving host, the key 43 | should be the same across scanners and receivers. The key is also used 44 | to initialize the random number generator for reproducible results. 45 | .IP \fB-o \fRos\fR 46 | Specify an operating system TCP stack to craft scan packets 47 | as. Valid \fIos\fR values include "win2k", "win9x", "macos9", 48 | "solaris28", "solaris26", "linux242", and "openbsd28". 49 | .IP \fB-p \fIports\fR 50 | Specify ports to scan as comma-separated, optionally ranged values 51 | (e.g. "21-23,25,80,111,135-139") or service names 52 | (e.g. "ftp,ssh,smtp"). By default, all 65535 TCP ports will be 53 | scanned. 54 | .IP \fB-s \fIsrcs\fR 55 | Specify source addresses to spoof as comma-separated IP addresses, 56 | ranges, prefixes, or hostnames 57 | (e.g. "1.2.3.4-1.2.3.242,10.0.1/24,10.0.4.1") for use in distributed 58 | scans where the receiver can sniff packets destined to these 59 | addresses. 60 | .IP \fIdsts\fR 61 | Specify target addresses to scan as comma-separated IP addresses, 62 | ranges, prefixes, or hostnames 63 | (e.g. "192.168.0.1-192.168.1.110,10/8,1.2.3.4"). 64 | .SH AUTHOR 65 | Dug Song 66 | 67 | -------------------------------------------------------------------------------- /compat/strsep.c: -------------------------------------------------------------------------------- 1 | /* $Id: strsep.c,v 1.1 2002/11/21 22:19:36 dugsong Exp $ */ 2 | /* $OpenBSD: strsep.c,v 1.3 1997/08/20 04:28:14 millert Exp $ */ 3 | 4 | /*- 5 | * Copyright (c) 1990, 1993 6 | * The Regents of the University of California. All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions 10 | * are met: 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. All advertising materials mentioning features or use of this software 17 | * must display the following acknowledgement: 18 | * This product includes software developed by the University of 19 | * California, Berkeley and its contributors. 20 | * 4. Neither the name of the University nor the names of its contributors 21 | * may be used to endorse or promote products derived from this software 22 | * without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 | * SUCH DAMAGE. 35 | */ 36 | 37 | #include 38 | #include 39 | 40 | /* 41 | * Get next token from string *stringp, where tokens are possibly-empty 42 | * strings separated by characters from delim. 43 | * 44 | * Writes NULs into the string at *stringp to end tokens. 45 | * delim need not remain constant from call to call. 46 | * On return, *stringp points past the last NUL written (if there might 47 | * be further tokens), or is NULL (if there are definitely no more tokens). 48 | * 49 | * If *stringp is NULL, strsep returns NULL. 50 | */ 51 | char * 52 | strsep(stringp, delim) 53 | register char **stringp; 54 | register const char *delim; 55 | { 56 | register char *s; 57 | register const char *spanp; 58 | register int c, sc; 59 | char *tok; 60 | 61 | if ((s = *stringp) == NULL) 62 | return (NULL); 63 | for (tok = s;;) { 64 | c = *s++; 65 | spanp = delim; 66 | do { 67 | if ((sc = *spanp++) == c) { 68 | if (c == 0) 69 | s = NULL; 70 | else 71 | s[-1] = 0; 72 | *stringp = s; 73 | return (tok); 74 | } 75 | } while (sc != 0); 76 | } 77 | /* NOTREACHED */ 78 | } 79 | -------------------------------------------------------------------------------- /bag-test.c: -------------------------------------------------------------------------------- 1 | /* 2 | * bag-test.c 3 | * 4 | * Copyright (c) 2002 Dug Song 5 | * 6 | * $Id: bag-test.c,v 1.2 2002/11/22 04:42:34 dugsong Exp $ 7 | */ 8 | 9 | #ifdef HAVE_CONFIG_H 10 | # include "config.h" 11 | #endif 12 | 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | 23 | #include "bag.h" 24 | #include "parse.h" 25 | 26 | static void 27 | usage(void) 28 | { 29 | fprintf(stderr, "Usage: bag-test\n"); 30 | exit(1); 31 | } 32 | 33 | static void 34 | help(void) 35 | { 36 | fprintf(stderr, "Commands:\n" 37 | "\tadd \n" 38 | "\tcount\n" 39 | "\tleft\n" 40 | "\tfirst\n" 41 | "\tlast\n" 42 | "\titer\n" 43 | "\tloop\n" 44 | "\trefill\n" 45 | "\tshuffle\n" 46 | "\tquit\n"); 47 | } 48 | 49 | static char * 50 | prompt(EditLine *el) 51 | { 52 | return ("bag-test> "); 53 | } 54 | 55 | static int 56 | print_value(uint32_t value, void *arg) 57 | { 58 | printf("%u\n", value); 59 | return (0); 60 | } 61 | 62 | int 63 | main(int argc, char *argv[]) 64 | { 65 | EditLine *el; 66 | History *el_hist; 67 | bag_t *bag; 68 | rand_t *rnd; 69 | uint32_t start, end; 70 | char *p, *cmd; 71 | 72 | if (argc != 1) 73 | usage(); 74 | 75 | el = el_init(argv[0], stdin, stdout); 76 | el_hist = history_init(); 77 | history(el_hist, H_EVENT, 100); 78 | el_set(el, EL_PROMPT, prompt); 79 | el_set(el, EL_EDITOR, "emacs"); 80 | el_set(el, EL_HIST, history, el_hist); 81 | 82 | bag = bag_open(); 83 | rnd = rand_open(); 84 | 85 | while ((p = (char *)el_gets(el, NULL)) != NULL) { 86 | history(el_hist, H_ENTER, p); 87 | 88 | strtok(p, "\r\n"); 89 | cmd = strsep(&p, " \t"); 90 | 91 | if (strcmp(cmd, "add") == 0) { 92 | if (parse_num_range(p, &start, &end) == 0) { 93 | if (bag_add_range(bag, start, end) < 0) 94 | warn("bag_add_range"); 95 | } else 96 | warnx("invalid range: %s", p); 97 | } else if (strcmp(cmd, "count") == 0) { 98 | print_value(bag_count(bag), NULL); 99 | } else if (strcmp(cmd, "left") == 0) { 100 | print_value(bag_left(bag), NULL); 101 | } else if (strcmp(cmd, "first") == 0) { 102 | if (bag_first(bag, &start) == 0) 103 | print_value(start, NULL); 104 | } else if (strcmp(cmd, "last") == 0) { 105 | if (bag_last(bag, &end) == 0) 106 | print_value(end, NULL); 107 | } else if (strcmp(cmd, "iter") == 0) { 108 | if (bag_iter(bag, &start) == 0) 109 | print_value(start, NULL); 110 | } else if (strcmp(cmd, "loop") == 0) { 111 | bag_loop(bag, print_value, NULL); 112 | } else if (strcmp(cmd, "refill") == 0) { 113 | if (bag_refill(bag) < 0) 114 | warn("bag_refill"); 115 | } else if (strcmp(cmd, "shuffle") == 0) { 116 | if (bag_shuffle(bag, rnd) < 0) 117 | warn("bag_shuffle"); 118 | bag_loop(bag, print_value, NULL); 119 | if (bag_refill(bag) < 0) 120 | warn("bag_refill"); 121 | } else if (strcmp(cmd, "quit") == 0) { 122 | break; 123 | } else 124 | help(); 125 | } 126 | history_end(el_hist); 127 | el_end(el); 128 | 129 | bag_close(bag); 130 | 131 | exit(0); 132 | } 133 | -------------------------------------------------------------------------------- /osstack.c: -------------------------------------------------------------------------------- 1 | /* 2 | * osstack.c 3 | * 4 | * Copyright (c) 2002 Dug Song 5 | * 6 | * $Id: osstack.c,v 1.5 2002/12/10 05:45:05 dugsong Exp $ 7 | */ 8 | 9 | #ifdef HAVE_CONFIG_H 10 | # include "config.h" 11 | #endif 12 | 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | 22 | #include "osstack.h" 23 | 24 | static struct osstack_syn { 25 | char *name; 26 | uint16_t ip_off; 27 | uint8_t ip_ttl; 28 | uint16_t th_win; 29 | uint8_t th_optlen; 30 | u_char *th_opt; 31 | } osstack_syns[] = { 32 | { "win2k", IP_DF, 128, 16384, 8, 33 | "\x02\x04\x05\xb4\x01\x01\x04\x02" }, 34 | { "win9x", IP_DF, 128, 8192, 4, 35 | "\x02\x04\x05\xb4" }, 36 | { "macos9", IP_DF, 255, 10720, 8, 37 | "\x02\x04\x05\xb4\x03\x03%N%N" }, 38 | { "sol28", IP_DF, 64, 24820, 8, 39 | "\x01\x01\x04\x02\x02\x04\x05\xb4" }, 40 | { "sol26", IP_DF, 255, 8760, 4, 41 | "\x02\x04\x05\xb4" }, 42 | { "linux242", IP_DF, 64, 5840, 20, 43 | "\x02\x04\x05\xb4\x04\x02\x08\x0a%D%N%N%N%N\x01\x03\x03%N" }, 44 | { "obsd28", 0, 64, 16384, 20, 45 | "\x02\x04\x05\xb4\x01\x03\x03%N\x01\x01\x08\x0a%D%N%N%N%N" } 46 | }; 47 | #define OSSTACK_SYN_SZ (sizeof(osstack_syns) / sizeof(osstack_syns[0])) 48 | 49 | struct osstack { 50 | struct osstack_syn *syn; 51 | }; 52 | 53 | static uint32_t tcp_now; 54 | 55 | static int 56 | _fmt_N(int pack, int len, blob_t *b, va_list *ap) 57 | { 58 | if (len) return (-1); 59 | 60 | if (pack) { 61 | uint8_t n = 0; 62 | return (blob_write(b, &n, sizeof(n))); 63 | } else 64 | return (0); 65 | } 66 | 67 | static int 68 | _osstack_syn_rewrite(struct osstack *o, struct ip_hdr *ip, size_t size) 69 | { 70 | struct osstack_syn *syn; 71 | struct tcp_hdr *tcp; 72 | blob_t b; 73 | int i; 74 | 75 | tcp = (struct tcp_hdr *)((u_char *)ip + IP_HDR_LEN); 76 | syn = o != NULL ? o->syn : &osstack_syns[ip->ip_src % OSSTACK_SYN_SZ]; 77 | 78 | i = ntohs(ip->ip_len) + syn->th_optlen; 79 | 80 | if (i < size) { 81 | ip->ip_off = htons(syn->ip_off); 82 | ip->ip_len = htons(i); 83 | ip->ip_ttl = syn->ip_ttl; 84 | tcp->th_win = htons(syn->th_win); 85 | tcp->th_off += syn->th_optlen >> 2; 86 | 87 | b.base = (u_char *)ip; 88 | b.off = IP_HDR_LEN + TCP_HDR_LEN; 89 | b.end = size; 90 | blob_pack(&b, syn->th_opt, tcp_now++); 91 | 92 | return (i); 93 | } 94 | return (-1); 95 | } 96 | 97 | struct osstack * 98 | osstack_open(const char *os) 99 | { 100 | struct osstack *o; 101 | rand_t *rnd; 102 | int i; 103 | 104 | rnd = rand_open(); 105 | tcp_now = rand_uint32(rnd) / 2; 106 | rand_close(rnd); 107 | 108 | blob_register_pack('N', _fmt_N); 109 | 110 | if ((o = calloc(1, sizeof(*o))) != NULL) { 111 | for (i = 0; i < OSSTACK_SYN_SZ; i++) { 112 | if (strncasecmp(os, osstack_syns[i].name, 113 | strlen(os)) == 0) { 114 | o->syn = &osstack_syns[i]; 115 | break; 116 | } 117 | } 118 | if (o->syn == NULL) { 119 | free(o); 120 | o = NULL; 121 | } 122 | } 123 | return (o); 124 | } 125 | 126 | int 127 | osstack_syn_rewrite(struct osstack *o, void *pkt, int size) 128 | { 129 | struct ip_hdr *ip = (struct ip_hdr *)pkt; 130 | 131 | if (ip->ip_p == IP_PROTO_TCP) 132 | return (_osstack_syn_rewrite(o, ip, size)); 133 | 134 | return (0); 135 | } 136 | 137 | struct osstack * 138 | osstack_close(struct osstack *o) 139 | { 140 | if (o != NULL) 141 | free(o); 142 | 143 | return (NULL); 144 | } 145 | -------------------------------------------------------------------------------- /acinclude.m4: -------------------------------------------------------------------------------- 1 | dnl 2 | dnl Check for 4.4 BSD sa_len member in sockaddr struct 3 | dnl 4 | dnl usage: AC_DNET_SOCKADDR_SA_LEN 5 | dnl results: HAVE_SOCKADDR_SA_LEN (defined) 6 | dnl 7 | AC_DEFUN(AC_DNET_SOCKADDR_SA_LEN, 8 | [AC_MSG_CHECKING(for sa_len in sockaddr struct) 9 | AC_CACHE_VAL(ac_cv_dnet_sockaddr_has_sa_len, 10 | AC_TRY_COMPILE([ 11 | # include 12 | # include ], 13 | [u_int i = sizeof(((struct sockaddr *)0)->sa_len)], 14 | ac_cv_dnet_sockaddr_has_sa_len=yes, 15 | ac_cv_dnet_sockaddr_has_sa_len=no)) 16 | AC_MSG_RESULT($ac_cv_dnet_sockaddr_has_sa_len) 17 | if test $ac_cv_dnet_sockaddr_has_sa_len = yes ; then 18 | AC_DEFINE(HAVE_SOCKADDR_SA_LEN, 1, 19 | [Define if sockaddr struct has sa_len.]) 20 | fi]) 21 | 22 | dnl 23 | dnl AC_LBL_LIBRARY_NET 24 | dnl 25 | dnl This test is for network applications that need socket() and 26 | dnl gethostbyname() -ish functions. Under Solaris, those applications 27 | dnl need to link with "-lsocket -lnsl". Under IRIX, they need to link 28 | dnl with "-lnsl" but should *not* link with "-lsocket" because 29 | dnl libsocket.a breaks a number of things (for instance: 30 | dnl gethostbyname() under IRIX 5.2, and snoop sockets under most 31 | dnl versions of IRIX). 32 | dnl 33 | dnl Unfortunately, many application developers are not aware of this, 34 | dnl and mistakenly write tests that cause -lsocket to be used under 35 | dnl IRIX. It is also easy to write tests that cause -lnsl to be used 36 | dnl under operating systems where neither are necessary (or useful), 37 | dnl such as SunOS 4.1.4, which uses -lnsl for TLI. 38 | dnl 39 | dnl This test exists so that every application developer does not test 40 | dnl this in a different, and subtly broken fashion. 41 | 42 | dnl It has been argued that this test should be broken up into two 43 | dnl seperate tests, one for the resolver libraries, and one for the 44 | dnl libraries necessary for using Sockets API. Unfortunately, the two 45 | dnl are carefully intertwined and allowing the autoconf user to use 46 | dnl them independantly potentially results in unfortunate ordering 47 | dnl dependancies -- as such, such component macros would have to 48 | dnl carefully use indirection and be aware if the other components were 49 | dnl executed. Since other autoconf macros do not go to this trouble, 50 | dnl and almost no applications use sockets without the resolver, this 51 | dnl complexity has not been implemented. 52 | dnl 53 | dnl The check for libresolv is in case you are attempting to link 54 | dnl statically and happen to have a libresolv.a lying around (and no 55 | dnl libnsl.a). 56 | dnl 57 | AC_DEFUN(AC_LBL_LIBRARY_NET, [ 58 | # Most operating systems have gethostbyname() in the default searched 59 | # libraries (i.e. libc): 60 | AC_CHECK_FUNC(gethostbyname, , 61 | # Some OSes (eg. Solaris) place it in libnsl: 62 | AC_CHECK_LIB(nsl, gethostbyname, , 63 | # Some strange OSes (SINIX) have it in libsocket: 64 | AC_CHECK_LIB(socket, gethostbyname, , 65 | # Unfortunately libsocket sometimes depends on libnsl. 66 | # AC_CHECK_LIB's API is essentially broken so the 67 | # following ugliness is necessary: 68 | AC_CHECK_LIB(socket, gethostbyname, 69 | LIBS="-lsocket -lnsl $LIBS", 70 | AC_CHECK_LIB(resolv, gethostbyname), 71 | -lnsl)))) 72 | AC_CHECK_FUNC(socket, , AC_CHECK_LIB(socket, socket, , 73 | AC_CHECK_LIB(socket, socket, LIBS="-lsocket -lnsl $LIBS", , 74 | -lnsl))) 75 | # DLPI needs putmsg under HPUX so test for -lstr while we're at it 76 | AC_CHECK_LIB(str, putmsg) 77 | ]) 78 | -------------------------------------------------------------------------------- /parse.c: -------------------------------------------------------------------------------- 1 | /* 2 | * parse.c 3 | * 4 | * Copyright (c) 2002 Dug Song 5 | * 6 | * $Id: parse.c,v 1.2 2002/11/22 04:42:35 dugsong Exp $ 7 | */ 8 | 9 | #ifdef HAVE_CONFIG_H 10 | # include "config.h" 11 | #endif 12 | 13 | #include 14 | 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "parse.h" 23 | 24 | static int 25 | _port_aton(const char *port, uint32_t *val) 26 | { 27 | struct servent *sp; 28 | 29 | if ((*val = atoi(port)) == 0) { 30 | if ((sp = getservbyname(port, "tcp")) != NULL) 31 | *val = ntohs(sp->s_port); 32 | else if ((sp = getservbyname(port, "udp")) != NULL) 33 | *val = ntohs(sp->s_port); 34 | } 35 | if (*val == 0 || *val > TCP_PORT_MAX) { 36 | errno = EINVAL; 37 | return (-1); 38 | } 39 | return (0); 40 | } 41 | 42 | static int 43 | _proto_aton(const char *proto, uint32_t *val) 44 | { 45 | struct protoent *pp; 46 | 47 | if ((*val = atoi(proto)) == 0) { 48 | if ((pp = getprotobyname(proto)) != NULL) 49 | *val = pp->p_proto; 50 | } 51 | if (*val == 0 || *val > IP_PROTO_MAX) { 52 | errno = EINVAL; 53 | return (-1); 54 | } 55 | return (0); 56 | } 57 | 58 | static int 59 | _aton(const char *num, uint32_t *val) 60 | { 61 | *val = atoi(num); 62 | return (0); 63 | } 64 | 65 | int 66 | parse_host_range(const char *range, uint32_t *start, uint32_t *end) 67 | { 68 | struct addr addr, bcast; 69 | uint32_t val, mask; 70 | u_int u[4]; 71 | char *p, *s; 72 | int ret = -1; 73 | 74 | if ((p = strdup(range)) == NULL) 75 | return (ret); 76 | 77 | if (addr_aton(p, &addr) == 0 && addr.addr_type == ADDR_TYPE_IP) { 78 | if (addr.addr_bits != IP_ADDR_BITS) { 79 | *start = htonl(ntohl(addr.addr_ip) + 1); 80 | addr_bcast(&addr, &bcast); 81 | *end = htonl(ntohl(bcast.addr_ip) - 1); 82 | } else 83 | *start = *end = addr.addr_ip; 84 | ret = 0; 85 | } else if ((s = strchr(p, '-')) != NULL) { 86 | *s = '\0'; 87 | if (ip_aton(p, start) == 0) { 88 | if (ip_aton(s + 1, end) == 0) { 89 | ret = 0; 90 | } else if ((val = atoi(s + 1)) > 0 && val <= 0xff) { 91 | *end = (*start & IP_CLASSC_NET) | htonl(val); 92 | ret = 0; 93 | } 94 | } 95 | } else if ((s = strchr(p, '/')) != NULL) { 96 | *s = '\0'; 97 | memset(u, 0, sizeof(u)); 98 | if (sscanf(p, "%d.%d.%d.%d", &u[0], &u[1], &u[2], &u[3]) > 0 && 99 | addr_btom(atoi(s + 1), &mask, IP_ADDR_LEN) == 0) { 100 | val = ((u[0]<<24) | (u[1]<<16) | (u[2]<<8) | u[3]) & 101 | ntohl(mask); 102 | *start = htonl(val + 1); 103 | *end = htonl((val | ~(ntohl(mask))) - 1); 104 | ret = 0; 105 | } 106 | } 107 | free(p); 108 | return (ret); 109 | } 110 | 111 | int 112 | parse_port_range(const char *range, uint32_t *start, uint32_t *end) 113 | { 114 | char *p, *s; 115 | int ret = -1; 116 | 117 | if ((p = strdup(range)) == NULL) 118 | return (ret); 119 | 120 | if ((s = strchr(p, '-')) != NULL) { 121 | *s = '\0'; 122 | if (_port_aton(p, start) == 0 && _port_aton(s + 1, end) == 0) 123 | ret = 0; 124 | } else if (_port_aton(p, start) == 0) { 125 | *end = *start; 126 | ret = 0; 127 | } 128 | free(p); 129 | return (ret); 130 | } 131 | 132 | int 133 | parse_proto_range(const char *range, uint32_t *start, uint32_t *end) 134 | { 135 | char *p, *s; 136 | int ret = -1; 137 | 138 | if ((p = strdup(range)) == NULL) 139 | return (ret); 140 | 141 | if ((s = strchr(p, '-')) != NULL) { 142 | *s = '\0'; 143 | if (_proto_aton(p, start) == 0 && _proto_aton(s + 1, end) == 0) 144 | ret = 0; 145 | } else if (_proto_aton(p, start) == 0) { 146 | *end = *start; 147 | ret = 0; 148 | } 149 | free(p); 150 | return (ret); 151 | } 152 | 153 | int 154 | parse_num_range(const char *range, uint32_t *start, uint32_t *end) 155 | { 156 | char *p, *s; 157 | int ret = -1; 158 | 159 | if ((p = strdup(range)) == NULL) 160 | return (ret); 161 | 162 | if ((s = strchr(p, '-')) != NULL) { 163 | *s = '\0'; 164 | if (_aton(p, start) == 0 && _aton(s + 1, end) == 0) 165 | ret = 0; 166 | } else if (_aton(p, start) == 0) { 167 | *end = *start; 168 | ret = 0; 169 | } 170 | free(p); 171 | return (ret); 172 | } 173 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * main.c 3 | * 4 | * Copyright (c) 2002 Dug Song 5 | * 6 | * $Id: main.c,v 1.9 2002/12/10 05:45:05 dugsong Exp $ 7 | */ 8 | 9 | #ifdef HAVE_CONFIG_H 10 | # include "config.h" 11 | #endif 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "dscan.h" 23 | 24 | static void 25 | usage(void) 26 | { 27 | FILE *output = NULL; 28 | char *pager = NULL; 29 | 30 | if (isatty(STDERR_FILENO)) { 31 | pager = getenv("PAGER"); 32 | if (pager == NULL) 33 | pager = "more"; 34 | output = popen(pager, "w"); 35 | } 36 | if (output == NULL) 37 | output = stderr; 38 | 39 | fprintf(output, 40 | "Usage: dscan MODE [OPTIONS] [dst]\n" 41 | " Modes:\n" 42 | " tcp TCP port scan/sweep\n" 43 | " ping ICMP echo sweep\n" 44 | " recv listen-only receiver\n" 45 | " Global opts:\n" 46 | " -k key scan/recv key (any string)\n" 47 | " -n no hostname lookups\n" 48 | " Scan opts:\n" 49 | " -b bitrate scan bitrate (e.g. 1.2m, default 128k)\n" 50 | " -o os OS stack to emulate (one of win9x, win2k, sol, linux, obsd)\n" 51 | " -r randomize scan order\n" 52 | " -s srcs decoy/receiver host/prefix list (e.g. decoyhost,recvhost)\n" 53 | " TCP scan opts:\n" 54 | " -f flags TCP flags (any combination of SAFRPUWE, default S)\n" 55 | " -p ports TCP port list (e.g. ftp,ssh,smtp,135-139, default 1-65535)\n" 56 | " Target opts:\n" 57 | " dst target host/prefix list (e.g. targethost,192.178/16,10/8)\n" 58 | ); 59 | if (pager != NULL) 60 | pclose(output); 61 | exit(1); 62 | } 63 | 64 | int 65 | main(int argc, char *argv[]) 66 | { 67 | dscan_t *dscan; 68 | uint32_t mode = 0; 69 | int c, status; 70 | pid_t pid; 71 | 72 | if (argc < 2) 73 | usage(); 74 | 75 | dscan = dscan_open(); 76 | 77 | if (strcmp(argv[1], "tcp") == 0) { 78 | mode = DSCAN_TCP; 79 | } else if (strcmp(argv[1], "ping") == 0) { 80 | mode = DSCAN_PING; 81 | } else if (strcmp(argv[1], "recv") == 0) { 82 | mode = DSCAN_RECV; 83 | } else 84 | usage(); 85 | 86 | dscan_set_mode(dscan, mode); 87 | dscan_set_cache(dscan, 8192); 88 | 89 | argc--, argv++; 90 | 91 | while ((c = getopt(argc, argv, "k:nb:o:rs:f:p:?")) != -1) { 92 | switch (c) { 93 | case 'k': 94 | if (dscan_set_key(dscan, optarg) < 0) 95 | errx(1, "couldn't set key"); 96 | break; 97 | case 'n': 98 | if (dscan_set_resolv(dscan, 0) < 0) 99 | errx(1, "couldn't disable hostname lookups"); 100 | break; 101 | case 'b': 102 | if (mode != DSCAN_RECV) { 103 | if (dscan_set_bitrate(dscan, optarg) < 0) 104 | errx(1, "couldn't set bitrate"); 105 | } else usage(); 106 | break; 107 | case 'o': 108 | if (mode != DSCAN_RECV) { 109 | if (dscan_set_osstack(dscan, optarg) < 0) 110 | errx(1, "couldn't set OS emulation"); 111 | } else usage(); 112 | break; 113 | case 'r': 114 | if (mode != DSCAN_RECV) { 115 | if (dscan_set_random(dscan, 1) < 0) 116 | errx(1, "couldn't set randomization"); 117 | } else usage(); 118 | break; 119 | case 's': 120 | if (mode != DSCAN_RECV) { 121 | if (dscan_set_srcs(dscan, optarg) < 0) 122 | errx(1, "couldn't set sources"); 123 | } else usage(); 124 | break; 125 | case 'f': 126 | if (mode == DSCAN_TCP) { 127 | if (dscan_set_tcpflags(dscan, optarg) < 0) 128 | errx(1, "couldn't set TCP flags"); 129 | } else usage(); 130 | break; 131 | case 'p': 132 | if (mode == DSCAN_TCP) { 133 | if (dscan_set_ports(dscan, optarg) < 0) 134 | errx(1, "couldn't set ports"); 135 | } else usage(); 136 | break; 137 | default: 138 | usage(); 139 | break; 140 | } 141 | } 142 | argc -= optind, argv += optind; 143 | 144 | if (argc == 1) { 145 | dscan_set_dsts(dscan, argv[0]); 146 | } else if (argc == 0) { 147 | dscan_set_dsts(dscan, "255.255.255.255"); 148 | if (mode != DSCAN_RECV) 149 | dscan_set_input(dscan, stdin); 150 | } else 151 | usage(); 152 | 153 | if (mode != DSCAN_RECV && (pid = fork()) != 0) { 154 | sleep(1); 155 | dscan_scan(dscan); 156 | waitpid(pid, &status, 0); 157 | } else 158 | dscan_recv(dscan); 159 | 160 | dscan_close(dscan); 161 | 162 | exit(0); 163 | } 164 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # $Id: configure.ac,v 1.6 2002/12/10 05:42:36 dugsong Exp $ 2 | 3 | AC_INIT(dscan, 1.0) 4 | AC_CONFIG_AUX_DIR(config) 5 | 6 | AM_INIT_AUTOMAKE(dscan, 1.0) 7 | AM_CONFIG_HEADER(config.h) 8 | 9 | # Initialize prefix. 10 | if test "$prefix" = "NONE"; then prefix="/usr/local"; fi 11 | 12 | # Checks for programs. 13 | AC_PROG_AWK 14 | AC_PROG_CC 15 | AC_PROG_INSTALL 16 | AC_PROG_LN_S 17 | 18 | # Checks for libraries. 19 | AC_LBL_LIBRARY_NET 20 | AC_CHECK_LIB(resolv, gethostbyname) 21 | 22 | # Checks for libevent 23 | AC_MSG_CHECKING(for libevent) 24 | AC_ARG_WITH(libevent, 25 | [ --with-libevent=DIR use libevent in DIR], 26 | [ case "$withval" in 27 | yes|no) 28 | AC_MSG_RESULT(no) 29 | ;; 30 | *) 31 | AC_MSG_RESULT($withval) 32 | if test -f $withval/include/event.h -a -f $withval/lib/libevent.a; then 33 | owd=`pwd` 34 | if cd $withval; then withval=`pwd`; cd $owd; fi 35 | EVENTINC="-I$withval/include" 36 | EVENTLIB="-L$withval/lib -levent" 37 | elif test -f $withval/event.h -a -f $withval/libevent.a; then 38 | owd=`pwd` 39 | if cd $withval; then withval=`pwd`; cd $owd; fi 40 | EVENTINC="-I$withval" 41 | EVENTLIB="-L$withval -levent" 42 | else 43 | AC_ERROR(event.h or libevent.a not found in $withval) 44 | fi 45 | ;; 46 | esac ], 47 | [ if test -f /usr/include/event.h -a -f /usr/lib/libevent.a; then 48 | EVENTLIB="-levent" 49 | elif test -f ${prefix}/include/event.h -a -f ${prefix}/lib/libevent.a; then 50 | EVENTINC="-I${prefix}/include" 51 | EVENTLIB="-L${prefix}/lib -levent" 52 | else 53 | AC_MSG_RESULT(no) 54 | AC_ERROR(libevent not found) 55 | fi 56 | AC_MSG_RESULT(yes) ] 57 | ) 58 | AC_SUBST(EVENTINC) 59 | AC_SUBST(EVENTLIB) 60 | 61 | # Checks for libpcap 62 | AC_MSG_CHECKING(for libpcap) 63 | AC_ARG_WITH(libpcap, 64 | [ --with-libpcap=DIR use libpcap in DIR], 65 | [ case "$withval" in 66 | yes|no) 67 | AC_MSG_RESULT(no) 68 | ;; 69 | *) 70 | AC_MSG_RESULT($withval) 71 | if test -f $withval/pcap.h -a -f $withval/libpcap.a; then 72 | owd=`pwd` 73 | if cd $withval; then withval=`pwd`; cd $owd; fi 74 | PCAPINC="-I$withval -I$withval/bpf" 75 | PCAPLIB="-L$withval -lpcap" 76 | elif test -f $withval/include/pcap.h -a \ 77 | -f $withval/include/net/bpf.h; then 78 | owd=`pwd` 79 | if cd $withval; then withval=`pwd`; cd $owd; fi 80 | PCAPINC="-I$withval/include" 81 | if test -f $withval/lib/libwpcap.a; then 82 | PCAPLIB="-L$withval/lib -lwpcap" 83 | else 84 | PCAPLIB="-L$withval/lib -lpcap" 85 | fi 86 | else 87 | AC_ERROR(pcap.h, net/bpf.h, or libpcap.a not found in $withval) 88 | fi 89 | ;; 90 | esac ], 91 | [ if test -f ${prefix}/include/pcap.h; then 92 | PCAPINC="-I${prefix}/include" 93 | if test -f ${prefix}/lib/libwpcap.a; then 94 | PCAPLIB="-L${prefix}/lib -lwpcap" 95 | else 96 | PCAPLIB="-L${prefix}/lib -lpcap" 97 | fi 98 | elif test -f /usr/include/pcap/pcap.h; then 99 | PCAPINC="-I/usr/include/pcap" 100 | PCAPLIB="-lpcap" 101 | elif test -f /usr/include/pcap.h; then 102 | PCAPLIB="-lpcap" 103 | elif test -f /sw/include/pcap.h; then 104 | PCAPINC="-I/sw/include" 105 | PCAPLIB="-L/sw/lib -lpcap" 106 | else 107 | AC_MSG_RESULT(no) 108 | AC_ERROR(libpcap not found) 109 | fi 110 | AC_MSG_RESULT(yes) ] 111 | ) 112 | AC_SUBST(PCAPINC) 113 | AC_SUBST(PCAPLIB) 114 | 115 | # Checks for (installed) libdnet 116 | AC_MSG_CHECKING(for libdnet) 117 | AC_ARG_WITH(libdnet, 118 | [ --with-libdnet=DIR use libdnet in DIR], 119 | [ case "$withval" in 120 | yes|no) 121 | AC_MSG_RESULT(no) 122 | ;; 123 | *) 124 | AC_MSG_RESULT($withval) 125 | if test -f $withval/src/libdnet.a; then 126 | DNETINC="-I$withval/include" 127 | DNETLIB="-L$withval/src -ldnet `$withval/dnet-config --libs`" 128 | elif test -x $withval/bin/dnet-config; then 129 | DNETINC="`$withval/bin/dnet-config --cflags`" 130 | DNETLIB="`$withval/bin/dnet-config --libs`" 131 | else 132 | AC_ERROR(dnet-config not found in $withval/bin) 133 | fi 134 | ;; 135 | esac ], 136 | [ if test -x ${prefix}/bin/dnet-config; then 137 | DNETINC="`${prefix}/bin/dnet-config --cflags`" 138 | DNETLIB="`${prefix}/bin/dnet-config --libs`" 139 | else 140 | AC_MSG_RESULT(no) 141 | AC_ERROR(libdnet not found) 142 | fi 143 | AC_MSG_RESULT(yes) ] 144 | ) 145 | AC_SUBST(DNETINC) 146 | AC_SUBST(DNETLIB) 147 | 148 | # Checks for header files. 149 | AC_HEADER_STDC 150 | AC_HEADER_SYS_WAIT 151 | 152 | # Checks for typedefs, structures, and compiler characteristics. 153 | AC_C_CONST 154 | AC_TYPE_PID_T 155 | AC_TYPE_SIZE_T 156 | AC_HEADER_TIME 157 | 158 | # Checks for library functions. 159 | AC_PROG_GCC_TRADITIONAL 160 | if test "$GCC" = yes ; then 161 | CFLAGS="$CFLAGS -Wall" 162 | fi 163 | 164 | AC_CHECK_FUNCS(clock_getres setproctitle sigaction strlcpy) 165 | AC_REPLACE_FUNCS(strsep) 166 | 167 | AC_CONFIG_FILES(Makefile) 168 | AC_OUTPUT 169 | -------------------------------------------------------------------------------- /ndb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ndb.c 3 | * 4 | * Copyright (c) 2002 Dug Song 5 | * 6 | * $Id: ndb.c,v 1.4 2002/12/10 05:45:05 dugsong Exp $ 7 | */ 8 | 9 | #ifdef HAVE_CONFIG_H 10 | # include "config.h" 11 | #endif 12 | 13 | #include 14 | 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "ndb.h" 24 | 25 | struct strtab { 26 | char *buf; 27 | int off; 28 | int size; 29 | }; 30 | 31 | static struct ndb { 32 | struct strtab st; 33 | int *ip; 34 | int *tcp; 35 | int *udp; 36 | } *ndb; 37 | 38 | static int 39 | strtab_put(struct strtab *st, const char *string) 40 | { 41 | char *p; 42 | int off, i = strlen(string); 43 | 44 | while (st->size - st->off < i + 1) { 45 | if (st->buf == NULL) { 46 | st->buf = malloc(BUFSIZ); 47 | st->off = 0; 48 | st->size = BUFSIZ; 49 | } else if ((p = realloc(st->buf, st->size << 1)) != NULL) { 50 | st->buf = p; 51 | st->size <<= 1; 52 | } else 53 | err(1, "realloc"); 54 | } 55 | strcpy(st->buf + st->off, string); 56 | off = st->off; 57 | st->off += i + 1; 58 | 59 | return (off); 60 | } 61 | 62 | static char * 63 | strtab_get(struct strtab *st, int off) 64 | { 65 | return (st->buf + off); 66 | } 67 | 68 | static void 69 | strtab_free(struct strtab *st) 70 | { 71 | free(st->buf); 72 | memset(st, 0, sizeof(*st)); 73 | } 74 | 75 | static void 76 | ndb_load_protocols(struct ndb *ndb, FILE *fp) 77 | { 78 | char *name, *num, buf[BUFSIZ]; 79 | int i; 80 | 81 | while (fgets(buf, sizeof(buf), fp) != NULL) { 82 | if (buf[0] == '#' || isspace((int)buf[0])) 83 | continue; 84 | 85 | name = strtok(buf, " \t"); 86 | num = strtok(NULL, " \t\r\n"); 87 | 88 | if (name && num && (i = atoi(num)) != 0) 89 | ndb->ip[i] = strtab_put(&ndb->st, name); 90 | } 91 | } 92 | 93 | static void 94 | ndb_load_services(struct ndb *ndb, FILE *fp) 95 | { 96 | char *name, *port, *proto, buf[BUFSIZ]; 97 | int i; 98 | 99 | while (fgets(buf, sizeof(buf), fp) != NULL) { 100 | if (buf[0] == '#' || isspace((int)buf[0])) 101 | continue; 102 | 103 | name = strtok(buf, " \t"); 104 | port = strtok(NULL, " \t/"); 105 | proto = strtok(NULL, " \t\r\n"); 106 | 107 | if (name && port && proto && (i = atoi(port)) != 0) { 108 | if (strcmp(proto, "tcp") == 0) { 109 | if (ndb->udp[i] && strcmp(name, 110 | strtab_get(&ndb->st, ndb->udp[i])) == 0) 111 | ndb->tcp[i] = ndb->udp[i]; 112 | else 113 | ndb->tcp[i] = strtab_put(&ndb->st, 114 | name); 115 | } else if (strcmp(proto, "udp") == 0) { 116 | if (ndb->tcp[i] && strcmp(name, 117 | strtab_get(&ndb->st, ndb->tcp[i])) == 0) 118 | ndb->udp[i] = ndb->tcp[i]; 119 | else 120 | ndb->udp[i] = strtab_put(&ndb->st, 121 | name); 122 | } 123 | } 124 | } 125 | } 126 | 127 | static FILE * 128 | path_fopen(const char *dirpath, const char *filepath, const char *mode) 129 | { 130 | FILE *fp = NULL; 131 | char *p, *q, *dir, *file; 132 | char dpath[BUFSIZ], fpath[BUFSIZ], fname[MAXPATHLEN]; 133 | 134 | strlcpy(dpath, dirpath, sizeof(dpath)); 135 | strlcpy(fpath, filepath, sizeof(fpath)); 136 | 137 | for (p = dpath; !fp && (dir = strsep(&p, ":")) != NULL; ) { 138 | for (q = fpath; !fp && (file = strsep(&q, ":")) != NULL; ) { 139 | snprintf(fname, sizeof(fname), "%s/%s", dir, file); 140 | fp = fopen(fname, mode); 141 | } 142 | } 143 | return (fp); 144 | } 145 | 146 | void 147 | ndb_open(const char *dirpath) 148 | { 149 | FILE *fp; 150 | 151 | if ((ndb = calloc(1, sizeof(*ndb))) != NULL) { 152 | ndb->ip = calloc(1, sizeof(ndb->ip[0]) * IP_PROTO_MAX); 153 | ndb->tcp = calloc(1, sizeof(ndb->tcp[0]) * TCP_PORT_MAX); 154 | ndb->udp = calloc(1, sizeof(ndb->udp[0]) * UDP_PORT_MAX); 155 | 156 | if ((fp = path_fopen(dirpath, 157 | "protocols:nmap-protocols", "r")) != NULL) { 158 | ndb_load_protocols(ndb, fp); 159 | fclose(fp); 160 | } 161 | if ((fp = path_fopen(dirpath, 162 | "services:nmap-services", "r")) != NULL) { 163 | ndb_load_services(ndb, fp); 164 | fclose(fp); 165 | } 166 | } 167 | } 168 | 169 | char * 170 | ndb_proto_name(int proto) 171 | { 172 | char *name, buf[32]; 173 | 174 | if ((name = strtab_get(&ndb->st, ndb->ip[proto])) == NULL) { 175 | snprintf(buf, sizeof(buf), "proto#%d", proto); 176 | name = buf; 177 | } 178 | return (name); 179 | } 180 | 181 | char * 182 | ndb_serv_name(int proto, int port) 183 | { 184 | char *name = NULL; 185 | 186 | if (proto == IP_PROTO_TCP && ndb->tcp[port]) 187 | name = strtab_get(&ndb->st, ndb->tcp[port]); 188 | else if (proto == IP_PROTO_UDP && ndb->udp[port]) 189 | name = strtab_get(&ndb->st, ndb->udp[port]); 190 | 191 | return (name ? name : "unknown"); 192 | } 193 | 194 | int 195 | ndb_serv_num(int proto, const char *name) 196 | { 197 | int i, port = 0; 198 | 199 | if (proto == IP_PROTO_TCP) { 200 | for (i = 0; i < TCP_PORT_MAX; i++) { 201 | if (ndb->tcp[i] && strcasecmp(name, 202 | strtab_get(&ndb->st, ndb->tcp[i])) == 0) { 203 | port = i; 204 | break; 205 | } 206 | } 207 | } else if (proto == IP_PROTO_UDP) { 208 | for (i = 0; i < UDP_PORT_MAX; i++) { 209 | if (ndb->udp[i] && strcasecmp(name, 210 | strtab_get(&ndb->st, ndb->udp[i])) == 0) { 211 | port = i; 212 | break; 213 | } 214 | } 215 | } 216 | return (port); 217 | } 218 | 219 | void 220 | ndb_close(void) 221 | { 222 | strtab_free(&ndb->st); 223 | free(ndb); 224 | ndb = NULL; 225 | } 226 | -------------------------------------------------------------------------------- /config/install-sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # install - install a program, script, or datafile 4 | # This comes from X11R5 (mit/util/scripts/install.sh). 5 | # 6 | # Copyright 1991 by the Massachusetts Institute of Technology 7 | # 8 | # Permission to use, copy, modify, distribute, and sell this software and its 9 | # documentation for any purpose is hereby granted without fee, provided that 10 | # the above copyright notice appear in all copies and that both that 11 | # copyright notice and this permission notice appear in supporting 12 | # documentation, and that the name of M.I.T. not be used in advertising or 13 | # publicity pertaining to distribution of the software without specific, 14 | # written prior permission. M.I.T. makes no representations about the 15 | # suitability of this software for any purpose. It is provided "as is" 16 | # without express or implied warranty. 17 | # 18 | # Calling this script install-sh is preferred over install.sh, to prevent 19 | # `make' implicit rules from creating a file called install from it 20 | # when there is no Makefile. 21 | # 22 | # This script is compatible with the BSD install script, but was written 23 | # from scratch. It can only install one file at a time, a restriction 24 | # shared with many OS's install programs. 25 | 26 | 27 | # set DOITPROG to echo to test this script 28 | 29 | # Don't use :- since 4.3BSD and earlier shells don't like it. 30 | doit="${DOITPROG-}" 31 | 32 | 33 | # put in absolute paths if you don't have them in your path; or use env. vars. 34 | 35 | mvprog="${MVPROG-mv}" 36 | cpprog="${CPPROG-cp}" 37 | chmodprog="${CHMODPROG-chmod}" 38 | chownprog="${CHOWNPROG-chown}" 39 | chgrpprog="${CHGRPPROG-chgrp}" 40 | stripprog="${STRIPPROG-strip}" 41 | rmprog="${RMPROG-rm}" 42 | mkdirprog="${MKDIRPROG-mkdir}" 43 | 44 | transformbasename="" 45 | transform_arg="" 46 | instcmd="$mvprog" 47 | chmodcmd="$chmodprog 0755" 48 | chowncmd="" 49 | chgrpcmd="" 50 | stripcmd="" 51 | rmcmd="$rmprog -f" 52 | mvcmd="$mvprog" 53 | src="" 54 | dst="" 55 | dir_arg="" 56 | 57 | while [ x"$1" != x ]; do 58 | case $1 in 59 | -c) instcmd="$cpprog" 60 | shift 61 | continue;; 62 | 63 | -d) dir_arg=true 64 | shift 65 | continue;; 66 | 67 | -m) chmodcmd="$chmodprog $2" 68 | shift 69 | shift 70 | continue;; 71 | 72 | -o) chowncmd="$chownprog $2" 73 | shift 74 | shift 75 | continue;; 76 | 77 | -g) chgrpcmd="$chgrpprog $2" 78 | shift 79 | shift 80 | continue;; 81 | 82 | -s) stripcmd="$stripprog" 83 | shift 84 | continue;; 85 | 86 | -t=*) transformarg=`echo $1 | sed 's/-t=//'` 87 | shift 88 | continue;; 89 | 90 | -b=*) transformbasename=`echo $1 | sed 's/-b=//'` 91 | shift 92 | continue;; 93 | 94 | *) if [ x"$src" = x ] 95 | then 96 | src=$1 97 | else 98 | # this colon is to work around a 386BSD /bin/sh bug 99 | : 100 | dst=$1 101 | fi 102 | shift 103 | continue;; 104 | esac 105 | done 106 | 107 | if [ x"$src" = x ] 108 | then 109 | echo "install: no input file specified" 110 | exit 1 111 | else 112 | true 113 | fi 114 | 115 | if [ x"$dir_arg" != x ]; then 116 | dst=$src 117 | src="" 118 | 119 | if [ -d $dst ]; then 120 | instcmd=: 121 | chmodcmd="" 122 | else 123 | instcmd=mkdir 124 | fi 125 | else 126 | 127 | # Waiting for this to be detected by the "$instcmd $src $dsttmp" command 128 | # might cause directories to be created, which would be especially bad 129 | # if $src (and thus $dsttmp) contains '*'. 130 | 131 | if [ -f $src -o -d $src ] 132 | then 133 | true 134 | else 135 | echo "install: $src does not exist" 136 | exit 1 137 | fi 138 | 139 | if [ x"$dst" = x ] 140 | then 141 | echo "install: no destination specified" 142 | exit 1 143 | else 144 | true 145 | fi 146 | 147 | # If destination is a directory, append the input filename; if your system 148 | # does not like double slashes in filenames, you may need to add some logic 149 | 150 | if [ -d $dst ] 151 | then 152 | dst="$dst"/`basename $src` 153 | else 154 | true 155 | fi 156 | fi 157 | 158 | ## this sed command emulates the dirname command 159 | dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` 160 | 161 | # Make sure that the destination directory exists. 162 | # this part is taken from Noah Friedman's mkinstalldirs script 163 | 164 | # Skip lots of stat calls in the usual case. 165 | if [ ! -d "$dstdir" ]; then 166 | defaultIFS=' 167 | ' 168 | IFS="${IFS-${defaultIFS}}" 169 | 170 | oIFS="${IFS}" 171 | # Some sh's can't handle IFS=/ for some reason. 172 | IFS='%' 173 | set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` 174 | IFS="${oIFS}" 175 | 176 | pathcomp='' 177 | 178 | while [ $# -ne 0 ] ; do 179 | pathcomp="${pathcomp}${1}" 180 | shift 181 | 182 | if [ ! -d "${pathcomp}" ] ; 183 | then 184 | $mkdirprog "${pathcomp}" 185 | else 186 | true 187 | fi 188 | 189 | pathcomp="${pathcomp}/" 190 | done 191 | fi 192 | 193 | if [ x"$dir_arg" != x ] 194 | then 195 | $doit $instcmd $dst && 196 | 197 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && 198 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && 199 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && 200 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi 201 | else 202 | 203 | # If we're going to rename the final executable, determine the name now. 204 | 205 | if [ x"$transformarg" = x ] 206 | then 207 | dstfile=`basename $dst` 208 | else 209 | dstfile=`basename $dst $transformbasename | 210 | sed $transformarg`$transformbasename 211 | fi 212 | 213 | # don't allow the sed command to completely eliminate the filename 214 | 215 | if [ x"$dstfile" = x ] 216 | then 217 | dstfile=`basename $dst` 218 | else 219 | true 220 | fi 221 | 222 | # Make a temp file name in the proper directory. 223 | 224 | dsttmp=$dstdir/#inst.$$# 225 | 226 | # Move or copy the file name to the temp name 227 | 228 | $doit $instcmd $src $dsttmp && 229 | 230 | trap "rm -f ${dsttmp}" 0 && 231 | 232 | # and set any options; do chmod last to preserve setuid bits 233 | 234 | # If any of these fail, we abort the whole thing. If we want to 235 | # ignore errors from any of these, just make sure not to ignore 236 | # errors from the above "$doit $instcmd $src $dsttmp" command. 237 | 238 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && 239 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && 240 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && 241 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && 242 | 243 | # Now rename the file to the real destination. 244 | 245 | $doit $rmcmd -f $dstdir/$dstfile && 246 | $doit $mvcmd $dsttmp $dstdir/$dstfile 247 | 248 | fi && 249 | 250 | 251 | exit 0 252 | -------------------------------------------------------------------------------- /recv.c: -------------------------------------------------------------------------------- 1 | /* 2 | * recv.c 3 | * 4 | * Copyright (c) 2002 Dug Song 5 | * 6 | * $Id: recv.c,v 1.16 2002/12/10 05:45:05 dugsong Exp $ 7 | */ 8 | 9 | #ifdef HAVE_CONFIG_H 10 | # include "config.h" 11 | #endif 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "ares.h" 29 | #include "bag.h" 30 | #include "dscan.h" 31 | #include "osstack.h" 32 | #include "dscan-int.h" 33 | #include "hash.h" 34 | #include "mysignal.h" 35 | #include "ndb.h" 36 | #include "pcaputil.h" 37 | #include "print.h" 38 | 39 | struct recv_result { 40 | uint32_t ip; 41 | int proto; 42 | int port; 43 | char data[20]; 44 | }; 45 | 46 | /* XXX - these should be in */ 47 | extern int (*event_sigcb)(void); 48 | extern int event_gotsig; 49 | 50 | static void 51 | recv_print(uint32_t ip, const char *name, void *arg) 52 | { 53 | struct recv_result *res = (struct recv_result *)arg; 54 | char pbuf[16]; 55 | 56 | snprintf(pbuf, sizeof(pbuf), "%s/%d", 57 | ndb_proto_name(res->proto), res->port); 58 | printf("%-16s %-34s %-10s %s\n", 59 | ip_ntoa(&res->ip), name ? name : "???", pbuf, res->data); 60 | 61 | fflush(stdout); 62 | free(res); 63 | } 64 | 65 | static void 66 | recv_pcap_cb(u_char *u, const struct pcap_pkthdr *h, const u_char *p) 67 | { 68 | struct dscan_dif *dif = (struct dscan_dif *)u; 69 | struct dscan_pkt *pkt; 70 | struct recv_result *res; 71 | struct timeval tv; 72 | uint32_t hash, tmp; 73 | int hash_ok; 74 | 75 | /* XXX - BPF bounds-checks up to the transport header in our filter */ 76 | pkt = (struct dscan_pkt *)(p + pcap_dloff(dif->pcap)); 77 | 78 | if (pkt->pkt_ip.ip_hl != 5 || 79 | (u_char *)&pkt->pkt_ip + ntohs(pkt->pkt_ip.ip_len) > p + h->len) 80 | return; 81 | 82 | /* Compute hash. */ 83 | hash_ok = 0; 84 | hash_init(&hash); 85 | hash_update(&hash, &dif->ctx->key, sizeof(dif->ctx->key)); 86 | hash_update(&hash, &pkt->pkt_ip.ip_p, sizeof(pkt->pkt_ip.ip_p)); 87 | hash_update(&hash, &pkt->pkt_ip.ip_dst, 4); 88 | hash_update(&hash, &pkt->pkt_ip.ip_src, 4); 89 | 90 | if (pkt->pkt_ip.ip_p == IP_PROTO_TCP) { 91 | hash_update(&hash, &pkt->pkt_tcp.th_sport, 2); 92 | if (hash == ntohl(pkt->pkt_tcp.th_ack) - 1) 93 | hash_ok = 1; 94 | } else if (pkt->pkt_ip.ip_p == IP_PROTO_ICMP && 95 | pkt->pkt_icmp.icmp_type == ICMP_ECHOREPLY) { 96 | hash_update(&hash, &pkt->pkt_icmp, 2); 97 | memcpy(&tmp, &pkt->pkt_icmp_msg.echo, 4); 98 | if (hash == ntohl(tmp)) 99 | hash_ok = 1; 100 | } 101 | /* Make sure this is a scan reply we haven't seen yet. */ 102 | if (hash_ok && dif->ctx->hcache[hash % dif->ctx->hcache_sz] != hash) { 103 | dif->ctx->hcache[hash % dif->ctx->hcache_sz] = hash; 104 | 105 | res = malloc(sizeof(*res)); 106 | res->ip = pkt->pkt_ip.ip_src; 107 | res->proto = pkt->pkt_ip.ip_p; 108 | 109 | if (res->proto == IP_PROTO_TCP) { 110 | res->port = ntohs(pkt->pkt_tcp.th_sport); 111 | strlcpy(res->data, ndb_serv_name(IP_PROTO_TCP, 112 | res->port), sizeof(res->data)); 113 | } else if (res->proto == IP_PROTO_ICMP && 114 | pkt->pkt_icmp.icmp_type == ICMP_ECHOREPLY) { 115 | quad_t usec; 116 | 117 | res->port = ICMP_ECHO; 118 | tv.tv_sec = ntohl(*(uint32_t *) 119 | &pkt->pkt_icmp_msg.echo.icmp_data[0]); 120 | tv.tv_usec = ntohl(*(uint32_t *) 121 | &pkt->pkt_icmp_msg.echo.icmp_data[4]); 122 | timersub(&h->ts, &tv, &tv); 123 | usec = (tv.tv_sec * 1000000) + tv.tv_usec; 124 | snprintf(res->data, sizeof(res->data), 125 | "echo (%d.%03d ms)", 126 | (int)(usec / 1000), (int)(usec % 1000)); 127 | } else 128 | err(1, "fubar"); 129 | 130 | /* Print reply. */ 131 | if (dif->ctx->resolv) 132 | ares_query(res->ip, recv_print, res); 133 | else 134 | recv_print(res->ip, "", res); 135 | } 136 | } 137 | 138 | static void 139 | recv_event_cb(int fd, short event, void *arg) 140 | { 141 | struct dscan_dif *dif = (struct dscan_dif *)arg; 142 | 143 | pcap_dispatch(dif->pcap, -1, recv_pcap_cb, (u_char *)dif); 144 | event_add(&dif->ev, NULL); /* XXX - older libevent */ 145 | } 146 | 147 | static void 148 | recv_spipe_cb(int fd, short event, void *arg) 149 | { 150 | struct dscan_ctx *ctx = (struct dscan_ctx *)arg; 151 | struct dscan_dif *dif; 152 | 153 | if (event == EV_READ) { 154 | read(fd, &ctx->duration, sizeof(ctx->duration)); 155 | event_set(&ctx->spipe_ev, -1, 0, recv_spipe_cb, ctx); 156 | event_add(&ctx->spipe_ev, &ctx->tv); 157 | } else { 158 | TAILQ_FOREACH(dif, &ctx->difs, next) 159 | event_del(&dif->ev); 160 | } 161 | } 162 | 163 | static void 164 | recv_drop_privs(void) 165 | { 166 | struct passwd *pw; 167 | 168 | if (geteuid() == 0) { 169 | if ((pw = getpwnam("nobody")) != NULL) { 170 | setuid(pw->pw_uid); 171 | } else 172 | warn("couldn't change UID to 'nobody'"); 173 | } 174 | } 175 | 176 | static int 177 | recv_sigcb(void) 178 | { 179 | return (-1); 180 | } 181 | 182 | static void 183 | recv_signal(int sig) 184 | { 185 | event_gotsig++; 186 | } 187 | 188 | void 189 | dscan_recv(struct dscan_ctx *ctx) 190 | { 191 | struct dscan_dif *dif; 192 | struct pcap_stat ps; 193 | 194 | #ifdef HAVE_SETPROCTITLE 195 | setproctitle("recv"); 196 | #endif 197 | ndb_open("/usr/local/share/nmap:/usr/share/nmap:/usr/lib/nmap:" 198 | "/etc/nmap:/usr/local/share/misc:/etc"); 199 | 200 | /* XXX - kqueue b0rked for BPF devices */ 201 | putenv("EVENT_NOKQUEUE=yes"); 202 | 203 | event_init(); 204 | 205 | if (ctx->resolv) 206 | ares_open(); 207 | 208 | if (ctx->mode != DSCAN_RECV) { 209 | event_set(&ctx->spipe_ev, ctx->spipe[0], EV_READ, 210 | recv_spipe_cb, ctx); 211 | event_add(&ctx->spipe_ev, NULL); 212 | } 213 | /* 214 | * Start sniffing on relevant interfaces. 215 | * XXX - assumes symmetric routes 216 | */ 217 | TAILQ_FOREACH(dif, &ctx->difs, next) { 218 | if (!(dif->pcap = pcap_open(dif->ifent.intf_name, 0, 31337)) || 219 | pcap_filter(dif->pcap, "tcp[13] = 0x12 or icmp[0] = 0")) { 220 | err(1, "couldn't open %s for sniffing", 221 | dif->ifent.intf_name); 222 | } 223 | if (ctx->mode == DSCAN_RECV) 224 | fprintf(stderr, "listening on %s\n", 225 | dif->ifent.intf_name); 226 | 227 | event_set(&dif->ev, pcap_fileno(dif->pcap), EV_READ, 228 | recv_event_cb, dif); 229 | event_add(&dif->ev, NULL); 230 | } 231 | event_sigcb = recv_sigcb; 232 | mysignal(SIGINT, recv_signal); 233 | mysignal(SIGTERM, recv_signal); 234 | mysignal(SIGPIPE, SIG_IGN); 235 | 236 | recv_drop_privs(); 237 | event_dispatch(); 238 | 239 | fprintf(stderr, "Scan finished: key %u", ctx->key); 240 | if (ctx->duration > 0) 241 | fprintf(stderr, ", %s", print_duration(ctx->duration)); 242 | fputc('\n', stderr); 243 | 244 | TAILQ_FOREACH(dif, &ctx->difs, next){ 245 | if (dif->pcap != NULL) { 246 | if (pcap_stats(dif->pcap, &ps) == 0 && ps.ps_drop > 0) 247 | warnx("%s: dropped %d packets", 248 | dif->ifent.intf_name, ps.ps_drop); 249 | pcap_close(dif->pcap); 250 | dif->pcap = NULL; 251 | } 252 | } 253 | #if 0 254 | if (ctx->resolv) 255 | ares_close(); 256 | #endif 257 | } 258 | -------------------------------------------------------------------------------- /config/missing: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Common stub for a few missing GNU programs while installing. 3 | # Copyright (C) 1996, 1997, 2001 Free Software Foundation, Inc. 4 | # Franc,ois Pinard , 1996. 5 | 6 | # This program is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2, or (at your option) 9 | # any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 19 | # 02111-1307, USA. 20 | 21 | if test $# -eq 0; then 22 | echo 1>&2 "Try \`$0 --help' for more information" 23 | exit 1 24 | fi 25 | 26 | # In the cases where this matters, `missing' is being run in the 27 | # srcdir already. 28 | if test -f configure.in; then 29 | configure_ac=configure.ac 30 | else 31 | configure_ac=configure.in 32 | fi 33 | 34 | case "$1" in 35 | 36 | -h|--h|--he|--hel|--help) 37 | echo "\ 38 | $0 [OPTION]... PROGRAM [ARGUMENT]... 39 | 40 | Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an 41 | error status if there is no known handling for PROGRAM. 42 | 43 | Options: 44 | -h, --help display this help and exit 45 | -v, --version output version information and exit 46 | 47 | Supported PROGRAM values: 48 | aclocal touch file \`aclocal.m4' 49 | autoconf touch file \`configure' 50 | autoheader touch file \`config.h.in' 51 | automake touch all \`Makefile.in' files 52 | bison create \`y.tab.[ch]', if possible, from existing .[ch] 53 | flex create \`lex.yy.c', if possible, from existing .c 54 | lex create \`lex.yy.c', if possible, from existing .c 55 | makeinfo touch the output file 56 | yacc create \`y.tab.[ch]', if possible, from existing .[ch]" 57 | ;; 58 | 59 | -v|--v|--ve|--ver|--vers|--versi|--versio|--version) 60 | echo "missing - GNU libit 0.0" 61 | ;; 62 | 63 | -*) 64 | echo 1>&2 "$0: Unknown \`$1' option" 65 | echo 1>&2 "Try \`$0 --help' for more information" 66 | exit 1 67 | ;; 68 | 69 | aclocal) 70 | echo 1>&2 "\ 71 | WARNING: \`$1' is missing on your system. You should only need it if 72 | you modified \`acinclude.m4' or \`$configure_ac'. You might want 73 | to install the \`Automake' and \`Perl' packages. Grab them from 74 | any GNU archive site." 75 | touch aclocal.m4 76 | ;; 77 | 78 | autoconf) 79 | echo 1>&2 "\ 80 | WARNING: \`$1' is missing on your system. You should only need it if 81 | you modified \`$configure_ac'. You might want to install the 82 | \`Autoconf' and \`GNU m4' packages. Grab them from any GNU 83 | archive site." 84 | touch configure 85 | ;; 86 | 87 | autoheader) 88 | echo 1>&2 "\ 89 | WARNING: \`$1' is missing on your system. You should only need it if 90 | you modified \`acconfig.h' or \`$configure_ac'. You might want 91 | to install the \`Autoconf' and \`GNU m4' packages. Grab them 92 | from any GNU archive site." 93 | files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' $configure_ac` 94 | test -z "$files" && files="config.h" 95 | touch_files= 96 | for f in $files; do 97 | case "$f" in 98 | *:*) touch_files="$touch_files "`echo "$f" | 99 | sed -e 's/^[^:]*://' -e 's/:.*//'`;; 100 | *) touch_files="$touch_files $f.in";; 101 | esac 102 | done 103 | touch $touch_files 104 | ;; 105 | 106 | automake) 107 | echo 1>&2 "\ 108 | WARNING: \`$1' is missing on your system. You should only need it if 109 | you modified \`Makefile.am', \`acinclude.m4' or \`$configure_ac'. 110 | You might want to install the \`Automake' and \`Perl' packages. 111 | Grab them from any GNU archive site." 112 | find . -type f -name Makefile.am -print | 113 | sed 's/\.am$/.in/' | 114 | while read f; do touch "$f"; done 115 | ;; 116 | 117 | bison|yacc) 118 | echo 1>&2 "\ 119 | WARNING: \`$1' is missing on your system. You should only need it if 120 | you modified a \`.y' file. You may need the \`Bison' package 121 | in order for those modifications to take effect. You can get 122 | \`Bison' from any GNU archive site." 123 | rm -f y.tab.c y.tab.h 124 | if [ $# -ne 1 ]; then 125 | eval LASTARG="\${$#}" 126 | case "$LASTARG" in 127 | *.y) 128 | SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` 129 | if [ -f "$SRCFILE" ]; then 130 | cp "$SRCFILE" y.tab.c 131 | fi 132 | SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` 133 | if [ -f "$SRCFILE" ]; then 134 | cp "$SRCFILE" y.tab.h 135 | fi 136 | ;; 137 | esac 138 | fi 139 | if [ ! -f y.tab.h ]; then 140 | echo >y.tab.h 141 | fi 142 | if [ ! -f y.tab.c ]; then 143 | echo 'main() { return 0; }' >y.tab.c 144 | fi 145 | ;; 146 | 147 | lex|flex) 148 | echo 1>&2 "\ 149 | WARNING: \`$1' is missing on your system. You should only need it if 150 | you modified a \`.l' file. You may need the \`Flex' package 151 | in order for those modifications to take effect. You can get 152 | \`Flex' from any GNU archive site." 153 | rm -f lex.yy.c 154 | if [ $# -ne 1 ]; then 155 | eval LASTARG="\${$#}" 156 | case "$LASTARG" in 157 | *.l) 158 | SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` 159 | if [ -f "$SRCFILE" ]; then 160 | cp "$SRCFILE" lex.yy.c 161 | fi 162 | ;; 163 | esac 164 | fi 165 | if [ ! -f lex.yy.c ]; then 166 | echo 'main() { return 0; }' >lex.yy.c 167 | fi 168 | ;; 169 | 170 | makeinfo) 171 | echo 1>&2 "\ 172 | WARNING: \`$1' is missing on your system. You should only need it if 173 | you modified a \`.texi' or \`.texinfo' file, or any other file 174 | indirectly affecting the aspect of the manual. The spurious 175 | call might also be the consequence of using a buggy \`make' (AIX, 176 | DU, IRIX). You might want to install the \`Texinfo' package or 177 | the \`GNU make' package. Grab either from any GNU archive site." 178 | file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` 179 | if test -z "$file"; then 180 | file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` 181 | file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` 182 | fi 183 | touch $file 184 | ;; 185 | 186 | *) 187 | echo 1>&2 "\ 188 | WARNING: \`$1' is needed, and you do not seem to have it handy on your 189 | system. You might have modified some files without having the 190 | proper tools for further handling them. Check the \`README' file, 191 | it often tells you about the needed prerequirements for installing 192 | this package. You may also peek at any GNU archive site, in case 193 | some other package would contain this missing \`$1' program." 194 | exit 1 195 | ;; 196 | esac 197 | 198 | exit 0 199 | -------------------------------------------------------------------------------- /bag.c: -------------------------------------------------------------------------------- 1 | /* 2 | * bag.c 3 | * 4 | * Copyright (c) 2002 Dug Song 5 | * 6 | * $Id: bag.c,v 1.3 2002/11/22 04:42:34 dugsong Exp $ 7 | */ 8 | 9 | #ifdef HAVE_CONFIG_H 10 | # include "config.h" 11 | #endif 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | 23 | #include "bag.h" 24 | 25 | #define TEADELTA 0x9e3779b9 26 | #define TEAROUNDS 32 27 | #define TEASBOXSIZE 128 28 | #define TEASBOXSHIFT 7 29 | 30 | struct bag_list { 31 | uint32_t *base; /* list head */ 32 | uint32_t cur; /* current index */ 33 | uint32_t nmemb; /* number of members */ 34 | uint32_t max; /* max allocated index */ 35 | }; 36 | 37 | struct bag_range { 38 | uint32_t start; /* range start */ 39 | uint32_t cur; /* current index */ 40 | uint32_t enc; /* encryption state */ 41 | uint32_t nmemb; /* range length */ 42 | TAILQ_ENTRY(bag_range) next; 43 | }; 44 | 45 | struct bag { 46 | struct bag_list list; 47 | TAILQ_HEAD(bag_range_head, bag_range) ranges; 48 | rand_t *rnd; 49 | uint32_t sbox[TEASBOXSIZE]; 50 | }; 51 | 52 | bag_t * 53 | bag_open(void) 54 | { 55 | bag_t *bag; 56 | 57 | if ((bag = calloc(1, sizeof(*bag))) != NULL) { 58 | TAILQ_INIT(&bag->ranges); 59 | } 60 | return (bag); 61 | } 62 | 63 | static int 64 | _bag_add_list(bag_t *bag, uint32_t val) 65 | { 66 | uint32_t *p; 67 | 68 | if (bag->list.base == NULL) { 69 | if ((bag->list.base = malloc(BUFSIZ)) == NULL) 70 | return (-1); 71 | bag->list.max = BUFSIZ / sizeof(val); 72 | } else if (bag->list.nmemb == bag->list.max) { 73 | bag->list.max <<= 1; 74 | if ((p = realloc(bag->list.base, bag->list.max)) == NULL) 75 | return (-1); 76 | bag->list.base = p; 77 | } 78 | bag->list.base[bag->list.nmemb++] = val; 79 | 80 | return (0); 81 | } 82 | 83 | int 84 | bag_add(bag_t *bag, uint32_t value) 85 | { 86 | return (_bag_add_list(bag, value)); 87 | } 88 | 89 | int 90 | bag_add_range(bag_t *bag, uint32_t start, uint32_t end) 91 | { 92 | struct bag_range *br; 93 | uint32_t i; 94 | int ret = -1; 95 | 96 | if (start == end) { 97 | ret = _bag_add_list(bag, start); 98 | } else if (end - start <= 4) { 99 | ret = 0; 100 | for (i = start; ret == 0 && i <= end; i++) { 101 | if (_bag_add_list(bag, i) < 0) 102 | ret = -1; 103 | } 104 | } else if (start < end && (br = calloc(1, sizeof(*br))) != NULL) { 105 | br->start = start; 106 | br->nmemb = end - start + 1; 107 | TAILQ_INSERT_TAIL(&bag->ranges, br, next); 108 | ret = 0; 109 | } 110 | return (ret); 111 | } 112 | 113 | uint32_t 114 | bag_count(bag_t *bag) 115 | { 116 | struct bag_list *bl = &bag->list; 117 | struct bag_range *br; 118 | uint32_t i = 0; 119 | 120 | i += bl->nmemb; 121 | 122 | TAILQ_FOREACH(br, &bag->ranges, next) { 123 | i += br->nmemb; 124 | } 125 | return (i); 126 | } 127 | 128 | uint32_t 129 | bag_left(bag_t *bag) 130 | { 131 | struct bag_list *bl = &bag->list; 132 | struct bag_range *br; 133 | uint32_t i = 0; 134 | 135 | i += bl->nmemb - bl->cur; 136 | 137 | TAILQ_FOREACH(br, &bag->ranges, next) { 138 | i += br->nmemb - br->cur; 139 | } 140 | return (i); 141 | } 142 | 143 | int 144 | bag_shuffle(bag_t *bag, rand_t *rnd) 145 | { 146 | int ret; 147 | 148 | bag->rnd = rnd; 149 | 150 | if ((ret = rand_get(bag->rnd, bag->sbox, sizeof(bag->sbox))) == 0) { 151 | bag_refill(bag); 152 | ret = rand_shuffle(bag->rnd, bag->list.base, 153 | bag->list.nmemb, sizeof(*bag->list.base)); 154 | } else 155 | bag->rnd = NULL; 156 | 157 | return (ret); 158 | } 159 | 160 | /* Modified (variable block length) TEA by Niels Provos */ 161 | 162 | static uint32_t 163 | _bag_iter(bag_t *bag, uint32_t enc, uint32_t nmemb) 164 | { 165 | uint32_t bits, mask, sboxmask, sum = 0; 166 | int i, left, right, kshift; 167 | 168 | if (bag->rnd != NULL) { 169 | for (bits = 0; nmemb > (1 << bits); bits++) 170 | ; 171 | 172 | left = bits / 2; 173 | right = bits - left; 174 | mask = (1 << bits) - 1; 175 | 176 | if (TEASBOXSIZE < (1 << left)) { 177 | sboxmask = TEASBOXSIZE - 1; 178 | kshift = TEASBOXSHIFT; 179 | } else { 180 | sboxmask = (1 << left) - 1; 181 | kshift = left; 182 | } 183 | for (i = 0; i < TEAROUNDS; i++) { 184 | sum += TEADELTA; 185 | enc ^= bag->sbox[(enc ^ sum) & sboxmask] << kshift; 186 | enc += sum; 187 | enc &= mask; 188 | enc = ((enc << left) | (enc >> right)) & mask; 189 | } 190 | } 191 | return (enc); 192 | } 193 | 194 | int 195 | bag_first(bag_t *bag, uint32_t *first) 196 | { 197 | struct bag_list *bl = &bag->list; 198 | struct bag_range *br; 199 | int i, enc; 200 | 201 | if (bl->nmemb > 0) { 202 | *first = bl->base[0]; 203 | } else if ((br = TAILQ_FIRST(&bag->ranges)) != NULL) { 204 | i = enc = 0; 205 | if (bag->rnd != NULL) { 206 | do { 207 | i = _bag_iter(bag, enc++, br->nmemb); 208 | } while (i >= br->nmemb); 209 | } 210 | *first = br->start + i; 211 | } else 212 | return (-1); 213 | 214 | return (0); 215 | } 216 | 217 | int 218 | bag_last(bag_t *bag, uint32_t *last) 219 | { 220 | struct bag_list *bl = &bag->list; 221 | struct bag_range *br; 222 | int cur, enc, i = 0; 223 | 224 | if ((br = TAILQ_LAST(&bag->ranges, bag_range_head)) != NULL) { 225 | if (bag->rnd != NULL) { 226 | for (cur = enc = 0; cur < br->nmemb; cur++) { 227 | do { 228 | i = _bag_iter(bag, enc++, br->nmemb); 229 | } while (i >= br->nmemb); 230 | } 231 | } else 232 | i = br->nmemb - 1; 233 | 234 | *last = br->start + i; 235 | } else if (bl->nmemb > 0) { 236 | *last = bl->base[bl->nmemb - 1]; 237 | } else 238 | return (-1); 239 | 240 | return (0); 241 | } 242 | 243 | int 244 | bag_iter(bag_t *bag, uint32_t *value) 245 | { 246 | struct bag_list *bl = &bag->list; 247 | struct bag_range *br; 248 | int i; 249 | 250 | if (bl->cur < bl->nmemb) { 251 | *value = bl->base[bl->cur++]; 252 | return (0); 253 | } 254 | for (br = TAILQ_FIRST(&bag->ranges); br; br = TAILQ_NEXT(br, next)) { 255 | if (br->cur < br->nmemb) { 256 | br->cur++; 257 | do { 258 | i = _bag_iter(bag, br->enc++, br->nmemb); 259 | } while (i >= br->nmemb); 260 | 261 | *value = br->start + i; 262 | return (0); 263 | } 264 | } 265 | return (-1); 266 | } 267 | 268 | int 269 | bag_loop(bag_t *bag, bag_handler callback, void *arg) 270 | { 271 | struct bag_list *bl; 272 | struct bag_range *br; 273 | int i, ret; 274 | 275 | for (bl = &bag->list; bl->cur < bl->nmemb; bl->cur++) { 276 | if ((ret = callback(bl->base[bl->cur], arg)) != 0) 277 | return (ret); 278 | } 279 | for (br = TAILQ_FIRST(&bag->ranges); br; br = TAILQ_NEXT(br, next)) { 280 | for ( ; br->cur < br->nmemb; br->cur++) { 281 | do { 282 | i = _bag_iter(bag, br->enc++, br->nmemb); 283 | } while (i >= br->nmemb); 284 | 285 | if ((ret = callback(br->start + i, arg)) != 0) 286 | return (ret); 287 | } 288 | } 289 | return (0); 290 | } 291 | 292 | int 293 | bag_refill(bag_t *bag) 294 | { 295 | struct bag_range *br; 296 | 297 | bag->list.cur = 0; 298 | 299 | TAILQ_FOREACH(br, &bag->ranges, next) { 300 | br->cur = 0; 301 | br->enc = 0; 302 | } 303 | return (0); 304 | } 305 | 306 | bag_t * 307 | bag_close(bag_t *bag) 308 | { 309 | struct bag_range *br; 310 | 311 | if (bag->list.base != NULL) 312 | free(bag->list.base); 313 | 314 | while ((br = TAILQ_FIRST(&bag->ranges)) != NULL) { 315 | TAILQ_REMOVE(&bag->ranges, br, next); 316 | free(br); 317 | } 318 | free(bag); 319 | 320 | return (NULL); 321 | } 322 | -------------------------------------------------------------------------------- /dscan.c: -------------------------------------------------------------------------------- 1 | /* 2 | * dscan.c 3 | * 4 | * Copyright (c) 2002 Dug Song 5 | * 6 | * $Id: dscan.c,v 1.8 2002/12/10 05:45:05 dugsong Exp $ 7 | */ 8 | 9 | #ifdef HAVE_CONFIG_H 10 | # include "config.h" 11 | #endif 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "bag.h" 30 | #include "dscan.h" 31 | #include "osstack.h" 32 | #include "dscan-int.h" 33 | #include "hash.h" 34 | #include "parse.h" 35 | 36 | struct dscan_ctx * 37 | dscan_open(void) 38 | { 39 | struct dscan_ctx *ctx; 40 | 41 | if ((ctx = calloc(1, sizeof(*ctx))) != NULL) { 42 | if ((ctx->intf = intf_open()) == NULL) 43 | return (dscan_close(ctx)); 44 | if ((ctx->rnd = rand_open()) == NULL) 45 | return (dscan_close(ctx)); 46 | ctx->key = rand_uint32(ctx->rnd); 47 | ctx->resolv = 1; 48 | pipe(ctx->spipe); 49 | TAILQ_INIT(&ctx->difs); 50 | } 51 | return (ctx); 52 | } 53 | 54 | int 55 | dscan_set_mode(struct dscan_ctx *ctx, uint32_t mode) 56 | { 57 | if (mode == DSCAN_RECV) { 58 | ctx->tv.tv_sec = DSCAN_RECV_TIMEOUT; 59 | ctx->tv.tv_usec = 0; 60 | } else if (mode == DSCAN_TCP || mode == DSCAN_PING) { 61 | ctx->mode = mode; 62 | if (mode == DSCAN_TCP) { 63 | ctx->proto = IP_PROTO_TCP; 64 | dscan_set_ports(ctx, "1-65535"); 65 | ctx->tcpflags = TH_SYN; 66 | } else if (mode == DSCAN_PING) { 67 | ctx->proto = IP_PROTO_ICMP; 68 | dscan_set_ports(ctx, "8"); 69 | } 70 | dscan_set_bitrate(ctx, "128k"); 71 | #ifdef HAVE_CLOCK_GETRES 72 | { 73 | struct timespec tp; 74 | clock_getres(CLOCK_REALTIME, &tp); 75 | ctx->tick_usec = (tp.tv_sec * 1000000) + (tp.tv_nsec / 1000); 76 | } 77 | #else 78 | ctx->tick_usec = 10 * 1000; 79 | #endif 80 | ctx->tick_usec *= 2; 81 | } else 82 | return (-1); 83 | 84 | return (0); 85 | } 86 | 87 | int 88 | dscan_set_cache(struct dscan_ctx *ctx, int cachesz) 89 | { 90 | ctx->hcache = calloc(1, sizeof(ctx->hcache[0]) * cachesz); 91 | 92 | if (ctx->hcache != NULL) { 93 | ctx->hcache_sz = cachesz; 94 | return (0); 95 | } 96 | return (-1); 97 | } 98 | 99 | int 100 | dscan_set_key(struct dscan_ctx *ctx, const char *key) 101 | { 102 | if ((ctx->key = atoi(key)) == 0) { 103 | hash_init(&ctx->key); 104 | hash_update(&ctx->key, key, strlen(key)); 105 | } 106 | return (rand_set(ctx->rnd, &ctx->key, sizeof(ctx->key))); 107 | } 108 | 109 | int 110 | dscan_set_resolv(struct dscan_ctx *ctx, int use_dns) 111 | { 112 | ctx->resolv = use_dns; 113 | return (0); 114 | } 115 | 116 | int 117 | dscan_set_dsts(struct dscan_ctx *ctx, const char *dsts) 118 | { 119 | struct dscan_dif *dif; 120 | struct intf_entry ifent; 121 | struct addr addr; 122 | uint32_t start, end; 123 | char *p, *host, hostlist[strlen(dsts) + 1]; 124 | 125 | strcpy(hostlist, dsts); 126 | 127 | for (p = hostlist; (host = strsep(&p, ",")) != NULL; ) { 128 | if (parse_host_range(host, &start, &end) < 0) 129 | return (-1); 130 | 131 | /* Look up outbound interface for this dst. */ 132 | ifent.intf_len = sizeof(ifent); 133 | addr_pack(&addr, ADDR_TYPE_IP, IP_ADDR_BITS, &start, 134 | IP_ADDR_LEN); 135 | 136 | if (intf_get_dst(ctx->intf, &ifent, &addr) < 0) 137 | return (-1); 138 | 139 | TAILQ_FOREACH(dif, &ctx->difs, next) { 140 | if (strcmp(dif->ifent.intf_name, ifent.intf_name) == 0) 141 | break; 142 | } 143 | if (dif == NULL) { 144 | if ((dif = calloc(1, sizeof(*dif))) == NULL) 145 | return (-1); 146 | dif->dsts = bag_open(); 147 | memcpy(&dif->ifent, &ifent, sizeof(ifent)); 148 | dif->ctx = ctx; 149 | TAILQ_INSERT_TAIL(&ctx->difs, dif, next); 150 | } 151 | if (bag_add_range(dif->dsts, ntohl(start), ntohl(end)) < 0) 152 | return (-1); 153 | } 154 | return (0); 155 | } 156 | 157 | int 158 | dscan_set_input(struct dscan_ctx *ctx, FILE *fp) 159 | { 160 | ctx->input = fp; 161 | return (0); 162 | } 163 | 164 | int 165 | dscan_set_bitrate(struct dscan_ctx *ctx, const char *bitrate) 166 | { 167 | char *ep; 168 | float dval, hz; 169 | 170 | errno = 0; 171 | dval = strtod(bitrate, &ep); 172 | 173 | if (bitrate[0] == '\0' || errno == ERANGE) 174 | return (-1); 175 | 176 | if (tolower(*ep) == 'k') 177 | dval *= 1000; 178 | else if (tolower(*ep) == 'm') 179 | dval *= (1000 * 1000); 180 | else if (tolower(*ep) == 'g') 181 | dval *= (1000 * 1000 * 1000); 182 | else if (*ep != '\0') 183 | return (-1); 184 | 185 | ctx->bitrate = (float)dval; 186 | hz = (float)1000000 / (float)ctx->tick_usec; 187 | ctx->tick_bytes = (uint32_t)((ctx->bitrate / 8) / hz); 188 | 189 | return (0); 190 | } 191 | 192 | int 193 | dscan_set_osstack(struct dscan_ctx *ctx, const char *os) 194 | { 195 | if ((ctx->osstack = osstack_open(os)) == NULL) 196 | return (-1); 197 | return (0); 198 | } 199 | 200 | int 201 | dscan_set_random(struct dscan_ctx *ctx, int use_rand) 202 | { 203 | ctx->random = use_rand; 204 | return (0); 205 | } 206 | 207 | int 208 | dscan_set_srcs(struct dscan_ctx *ctx, const char *srcs) 209 | { 210 | uint32_t start, end; 211 | char *p, *host, hostlist[strlen(srcs) + 1]; 212 | int ret = 0; 213 | 214 | strcpy(hostlist, srcs); 215 | ctx->srcs = bag_open(); 216 | 217 | for (p = hostlist; (host = strsep(&p, ",")) != NULL && ret == 0; ) { 218 | if ((ret = parse_host_range(host, &start, &end)) == 0) 219 | ret = bag_add_range(ctx->srcs, 220 | ntohl(start), ntohl(end)); 221 | } 222 | if (ret != 0) 223 | ctx->srcs = bag_close(ctx->srcs); 224 | 225 | return (ret); 226 | } 227 | 228 | int 229 | dscan_set_tcpflags(struct dscan_ctx *ctx, const char *tcpflags) 230 | { 231 | const char *p; 232 | u_char flags = 0; 233 | 234 | for (p = tcpflags; *p != '\0'; p++) { 235 | if (*p == 'F') flags |= TH_FIN; 236 | else if (*p == 'S') flags |= TH_SYN; 237 | else if (*p == 'R') flags |= TH_RST; 238 | else if (*p == 'P') flags |= TH_PUSH; 239 | else if (*p == 'A') flags |= TH_ACK; 240 | else if (*p == 'U') flags |= TH_URG; 241 | else if (*p == 'W') flags |= TH_CWR; 242 | else if (*p == 'E') flags |= TH_ECE; 243 | else if (*p != 'N' && *p != '0') 244 | return (-1); 245 | } 246 | ctx->tcpflags = flags; 247 | return (0); 248 | } 249 | 250 | int 251 | dscan_set_ports(struct dscan_ctx *ctx, const char *ports) 252 | { 253 | uint32_t start, end; 254 | char *p, *port, portlist[strlen(ports) + 1]; 255 | int ret = 0; 256 | 257 | strcpy(portlist, ports); 258 | if (ctx->ports != NULL) 259 | bag_close(ctx->ports); 260 | ctx->ports = bag_open(); 261 | 262 | for (p = portlist; (port = strsep(&p, ",")) != NULL && ret == 0; ) { 263 | if ((ret = parse_port_range(port, &start, &end)) == 0) 264 | ret = bag_add_range(ctx->ports, start, end); 265 | } 266 | if (ret != 0) 267 | ctx->ports = bag_close(ctx->ports); 268 | 269 | return (ret); 270 | } 271 | 272 | struct dscan_ctx * 273 | dscan_close(struct dscan_ctx *ctx) 274 | { 275 | struct dscan_dif *dif, *next; 276 | 277 | if (ctx->spipe[0] > 0) 278 | close(ctx->spipe[0]); 279 | if (ctx->spipe[1] > 0) 280 | close(ctx->spipe[1]); 281 | 282 | ctx->key = 0; 283 | if (ctx->rnd != NULL) 284 | ctx->rnd = rand_close(ctx->rnd); 285 | if (ctx->intf != NULL) 286 | ctx->intf = intf_close(ctx->intf); 287 | 288 | for (dif = TAILQ_FIRST(&ctx->difs); dif != NULL; dif = next) { 289 | next = TAILQ_NEXT(dif, next); 290 | bag_close(dif->dsts); 291 | free(dif); 292 | } 293 | if (ctx->hcache != NULL) 294 | free(ctx->hcache); 295 | if (ctx->ports != NULL) 296 | ctx->ports = bag_close(ctx->ports); 297 | if (ctx->srcs != NULL) 298 | ctx->srcs = bag_close(ctx->srcs); 299 | 300 | free(ctx); 301 | 302 | return (NULL); 303 | } 304 | -------------------------------------------------------------------------------- /scan.c: -------------------------------------------------------------------------------- 1 | /* 2 | * scan.c 3 | * 4 | * Copyright (c) 2002 Dug Song 5 | * 6 | * $Id: scan.c,v 1.10 2002/12/10 05:45:05 dugsong Exp $ 7 | */ 8 | 9 | #ifdef HAVE_CONFIG_H 10 | # include "config.h" 11 | #endif 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "bag.h" 30 | #include "dscan.h" 31 | #include "osstack.h" 32 | #include "dscan-int.h" 33 | #include "hash.h" 34 | #include "mysignal.h" 35 | #include "print.h" 36 | 37 | static uint32_t scan_gotsig; 38 | static uint32_t scan_ticks; 39 | 40 | static int 41 | scan_send(ip_t *ip, struct dscan_ctx *ctx, 42 | uint32_t src, uint32_t dst, uint16_t dport) 43 | { 44 | struct dscan_pkt *pkt; 45 | struct timeval tv; 46 | uint32_t hash; 47 | u_char buf[BUFSIZ]; 48 | int len; 49 | 50 | hash_init(&hash); 51 | hash_update(&hash, &ctx->key, sizeof(ctx->key)); 52 | hash_update(&hash, &ctx->proto, 1); 53 | hash_update(&hash, &src, 4); 54 | hash_update(&hash, &dst, 4); 55 | 56 | pkt = (struct dscan_pkt *)buf; 57 | 58 | if (ctx->mode == DSCAN_TCP) { 59 | len = IP_HDR_LEN + TCP_HDR_LEN; 60 | ip_pack_hdr(&pkt->pkt_ip, 0, len, rand_uint16(ctx->rnd), 61 | 0, 255, ctx->proto, src, dst); 62 | tcp_pack_hdr(&pkt->pkt_tcp, rand_uint16(ctx->rnd), dport, 63 | 0, 0, ctx->tcpflags, TCP_WIN_MAX, 0); 64 | hash_update(&hash, &pkt->pkt_tcp.th_dport, 2); 65 | pkt->pkt_tcp.th_seq = htonl(hash); 66 | len = osstack_syn_rewrite(ctx->osstack, buf, sizeof(buf)); 67 | } else if (ctx->mode == DSCAN_PING) { 68 | len = IP_HDR_LEN + ICMP_HDR_LEN + 12; 69 | ip_pack_hdr(&pkt->pkt_ip, 0, len, rand_uint16(ctx->rnd), 70 | 0, 255, ctx->proto, src, dst); 71 | pkt->pkt_icmp.icmp_type = ICMP_ECHOREPLY; 72 | pkt->pkt_icmp.icmp_code = ICMP_CODE_NONE; 73 | hash_update(&hash, &pkt->pkt_icmp, 2); 74 | hash = htonl(hash); 75 | 76 | pkt->pkt_icmp.icmp_type = ICMP_ECHO; 77 | memcpy(&pkt->pkt_icmp_msg.echo, &hash, 4); 78 | 79 | gettimeofday(&tv, NULL); 80 | *(uint32_t *)&pkt->pkt_icmp_msg.echo.icmp_data[0] = 81 | htonl(tv.tv_sec); 82 | *(uint32_t *)&pkt->pkt_icmp_msg.echo.icmp_data[4] = 83 | htonl(tv.tv_usec); 84 | } else 85 | errx(1, "unknown mode %d", ctx->mode); 86 | 87 | ip_checksum(pkt, len); 88 | 89 | return (ip_send(ip, pkt, len)); 90 | } 91 | 92 | static void 93 | scan_dst(ip_t *ip, struct dscan_ctx *ctx, struct dscan_dif *dif) 94 | { 95 | uint32_t sip, dip, port, n, bytes = 0; 96 | 97 | sip = dif->ifent.intf_addr.addr_ip; 98 | 99 | while (bag_iter(dif->dsts, &dip) == 0 && !scan_gotsig) { 100 | while (bag_iter(ctx->ports, &port) == 0 && !scan_gotsig) { 101 | if (ctx->srcs != NULL) { 102 | while (bag_iter(ctx->srcs, &sip) < 0) 103 | bag_refill(ctx->srcs); 104 | sip = htonl(sip); 105 | } 106 | while ((n = scan_send(ip, ctx, sip, htonl(dip), 107 | port)) < 0) 108 | warn("send"); 109 | 110 | bytes += n; 111 | 112 | if (bytes > ctx->tick_bytes * scan_ticks) { 113 | if (scan_ticks > 100000) { 114 | scan_ticks = 1; 115 | bytes = 0; 116 | } 117 | pause(); 118 | } 119 | } 120 | bag_refill(ctx->ports); 121 | } 122 | } 123 | 124 | static void 125 | scan_dst_input(ip_t *ip, struct dscan_ctx *ctx, struct dscan_dif *dif) 126 | { 127 | char buf[BUFSIZ]; 128 | uint32_t n, sip, dip, port, bytes = 0; 129 | 130 | sip = dif->ifent.intf_addr.addr_ip; 131 | 132 | while (!scan_gotsig) { 133 | if (fgets(buf, sizeof(buf), ctx->input) == NULL) { 134 | if (feof(ctx->input) || errno != EINTR) 135 | break; 136 | continue; 137 | } 138 | if (buf[0] == '#' || isspace((int)buf[0])) 139 | continue; 140 | 141 | fputs(buf, stdout); 142 | strtok(buf, " \t\r\n"); 143 | 144 | if (ip_pton(buf, &dip) == 0) { 145 | while (bag_iter(ctx->ports, &port) == 0 && 146 | !scan_gotsig) { 147 | while ((n = scan_send(ip, ctx, sip, dip, 148 | port)) < 0) 149 | warn("send"); 150 | bytes += n; 151 | if (bytes > ctx->tick_bytes * scan_ticks) { 152 | if (scan_ticks > 100000) { 153 | scan_ticks = 1; 154 | bytes = 0; 155 | } 156 | pause(); 157 | } 158 | } 159 | bag_refill(ctx->ports); 160 | } 161 | } 162 | } 163 | 164 | static void 165 | scan_dst_random(ip_t *ip, struct dscan_ctx *ctx, struct dscan_dif *dif) 166 | { 167 | uint32_t sip, dip, port, fip, fport, n, bytes = 0; 168 | int i, j, mod; 169 | 170 | i = bag_count(dif->dsts); 171 | j = bag_count(ctx->ports); 172 | 173 | /* XXX - ugh, gross hack */ 174 | if ((mod = i % j) == i && i > 1) 175 | mod = j % i; 176 | if (mod == 0) 177 | bag_add(dif->dsts, 0); 178 | 179 | if (ctx->srcs != NULL) 180 | bag_shuffle(ctx->srcs, ctx->rnd); 181 | bag_shuffle(dif->dsts, ctx->rnd); 182 | bag_shuffle(ctx->ports, ctx->rnd); 183 | 184 | bag_iter(dif->dsts, &fip); 185 | bag_iter(ctx->ports, &fport); 186 | dip = fip, port = fport; 187 | sip = dif->ifent.intf_addr.addr_ip; 188 | 189 | do { 190 | if (ctx->srcs != NULL) { 191 | while (bag_iter(ctx->srcs, &sip) < 0) 192 | bag_refill(ctx->srcs); 193 | sip = htonl(sip); 194 | } 195 | if (dip != 0) { 196 | while ((n = scan_send(ip, ctx, sip, htonl(dip), 197 | port)) < 0) 198 | warn("send"); 199 | 200 | bytes += n; 201 | } 202 | if (bytes > ctx->tick_bytes * scan_ticks) { 203 | if (scan_ticks > 100000) { 204 | scan_ticks = 1; 205 | bytes = 0; 206 | } 207 | pause(); 208 | } 209 | while (bag_iter(dif->dsts, &dip) < 0) 210 | bag_refill(dif->dsts); 211 | 212 | while (bag_iter(ctx->ports, &port) < 0) 213 | bag_refill(ctx->ports); 214 | } 215 | while (!(dip == fip && port == fport) && !scan_gotsig); 216 | } 217 | 218 | static void 219 | scan_signal(int sig) 220 | { 221 | if (sig == SIGALRM) 222 | scan_ticks++; 223 | else 224 | scan_gotsig++; 225 | } 226 | 227 | #define timeval_to_float_usec(tv) \ 228 | ((float)((tv)->tv_sec * 1000000) + (float)(tv)->tv_usec) 229 | 230 | void 231 | dscan_scan(struct dscan_ctx *ctx) 232 | { 233 | struct timeval tv; 234 | struct dscan_dif *dif; 235 | float start, end; 236 | int difcnt = 0; 237 | ip_t *ip; 238 | 239 | close(ctx->spipe[0]); 240 | #ifdef HAVE_SETPROCTITLE 241 | setproctitle("scan"); 242 | #endif 243 | if ((ip = ip_open()) == NULL) 244 | err(1, "couldn't open raw socket"); 245 | 246 | /* Print our scan configuration. */ 247 | TAILQ_FOREACH(dif, &ctx->difs, next) { 248 | difcnt += bag_count(dif->dsts); 249 | } 250 | fprintf(stderr, "Scan starting: key %u", ctx->key); 251 | if (ctx->input == NULL) 252 | fprintf(stderr, ", ETA %s", print_duration((float) 253 | (difcnt * bag_count(ctx->ports) * 48 * 8) / ctx->bitrate)); 254 | fputc('\n', stderr); 255 | 256 | mysignal(SIGINT, scan_signal); 257 | mysignal(SIGTERM, scan_signal); 258 | mysignal(SIGALRM, scan_signal); 259 | mysignal(SIGPIPE, SIG_IGN); 260 | 261 | ualarm(ctx->tick_usec, ctx->tick_usec); 262 | 263 | gettimeofday(&tv, NULL); 264 | start = timeval_to_float_usec(&tv); 265 | 266 | // XXX - have fxn ptr to scan_dst* 267 | for (dif = TAILQ_FIRST(&ctx->difs); 268 | dif != TAILQ_END(&ctx->difs) && !scan_gotsig; 269 | dif = TAILQ_NEXT(dif, next)) { 270 | if (ctx->random) { 271 | scan_dst_random(ip, ctx, dif); 272 | } else if (ctx->input != NULL) { 273 | scan_dst_input(ip, ctx, dif); 274 | } else 275 | scan_dst(ip, ctx, dif); 276 | } 277 | gettimeofday(&tv, NULL); 278 | end = timeval_to_float_usec(&tv); 279 | ctx->duration = (end - start) / 1000000.0; 280 | 281 | ualarm(0, 0); 282 | 283 | write(ctx->spipe[1], &ctx->duration, sizeof(ctx->duration)); 284 | 285 | ip_close(ip); 286 | } 287 | -------------------------------------------------------------------------------- /ares.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ares.c 3 | * 4 | * Copyright (c) 2002 Dug Song 5 | * 6 | * $Id: ares.c,v 1.4 2002/11/21 22:19:35 dugsong Exp $ 7 | */ 8 | 9 | #ifdef HAVE_CONFIG_H 10 | # include "config.h" 11 | #endif 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "ares.h" 33 | 34 | struct ares_cb { 35 | ares_callback callback; 36 | void *arg; 37 | TAILQ_ENTRY(ares_cb) next; 38 | }; 39 | 40 | struct ares_node { 41 | uint16_t qid; 42 | uint8_t retries; 43 | uint8_t done; 44 | 45 | uint32_t ip; 46 | char name[MAXHOSTNAMELEN]; 47 | TAILQ_HEAD(, ares_cb) callbacks; 48 | 49 | struct timeval tv; 50 | struct event ev; 51 | RB_ENTRY(ares_node) next; 52 | }; 53 | 54 | union ares_pkt { 55 | HEADER hdr; 56 | u_char buf[PACKETSZ * 2]; 57 | }; 58 | 59 | RB_HEAD(ares_tree, ares_node) ares_tree; 60 | static struct event ares_ev; 61 | static struct timeval ares_tv = { RES_TIMEOUT, 0 }; 62 | static int ares_fd; 63 | static uint32_t ares_qcnt; 64 | 65 | static int 66 | _ares_cmp(struct ares_node *a, struct ares_node *b) 67 | { 68 | return (memcmp(&a->ip, &b->ip, sizeof(a->ip))); 69 | } 70 | 71 | RB_PROTOTYPE(ares_tree, ares_node, next, _ares_cmp); 72 | RB_GENERATE(ares_tree, ares_node, next, _ares_cmp); 73 | 74 | static void _ares_timeout(int fd, short event, void *arg); 75 | 76 | static int 77 | _ares_add_callback(struct ares_node *np, ares_callback callback, void *arg) 78 | { 79 | struct ares_cb *cb; 80 | 81 | if ((cb = malloc(sizeof(*cb))) != NULL) { 82 | cb->callback = callback; 83 | cb->arg = arg; 84 | TAILQ_INSERT_TAIL(&np->callbacks, cb, next); 85 | return (0); 86 | } 87 | return (-1); 88 | } 89 | 90 | static void 91 | _ares_do_callbacks(struct ares_node *np) 92 | { 93 | struct ares_cb *cb, *next; 94 | 95 | for (cb = TAILQ_FIRST(&np->callbacks); cb != TAILQ_END(&np->callbacks); 96 | cb = next) { 97 | next = TAILQ_NEXT(cb, next); 98 | cb->callback(np->ip, !np->done ? NULL : np->name, cb->arg); 99 | free(cb); 100 | } 101 | TAILQ_INIT(&np->callbacks); 102 | } 103 | 104 | static void 105 | _ares_send(int fd, short event, void *arg) 106 | { 107 | struct ares_node *np = (struct ares_node *)arg; 108 | static int nsindex; 109 | union ares_pkt pkt; 110 | char dname[MAXDNAME]; 111 | uint32_t ms; 112 | u_char *p; 113 | int i; 114 | 115 | /* Build our PTR query. */ 116 | p = (u_char *)&np->ip; 117 | snprintf(dname, sizeof(dname), "%d.%d.%d.%d.in-addr.arpa", 118 | p[3]&0xff, p[2]&0xff, p[1]&0xff, p[0]&0xff); 119 | 120 | i = res_mkquery(QUERY, dname, C_IN, T_PTR, NULL, 0, NULL, 121 | pkt.buf, sizeof(pkt.buf)); 122 | 123 | np->qid = pkt.hdr.id; 124 | 125 | /* Round-robin queries to all configured nameservers. */ 126 | if (++nsindex >= _res.nscount) 127 | nsindex = 0; 128 | 129 | if (sendto(ares_fd, pkt.buf, i, 0, 130 | (struct sockaddr *)&_res.nsaddr_list[nsindex], 131 | #ifdef HAVE_SOCKADDR_SA_LEN 132 | _res.nsaddr.sin_len 133 | #else 134 | sizeof(struct sockaddr_in) 135 | #endif 136 | ) == i) { 137 | /* Make sure our response handler is active. */ 138 | event_add(&ares_ev, &ares_tv); 139 | 140 | /* Schedule response timeout. */ 141 | np->tv.tv_sec = RES_TIMEOUT; 142 | np->tv.tv_usec = 0; 143 | event_set(&np->ev, -1, 0, _ares_timeout, np); 144 | event_add(&np->ev, &np->tv); 145 | } else if (errno == ENOBUFS) { 146 | /* Reschedule our query. */ 147 | ms = ((np->tv.tv_sec * 1000) + (np->tv.tv_usec / 1000)) << 1; 148 | np->tv.tv_sec = ms / 1000; 149 | np->tv.tv_usec = (ms % 1000) * 1000; 150 | event_add(&np->ev, &np->tv); 151 | } else { 152 | /* Unrecoverable failure. */ 153 | RB_REMOVE(ares_tree, &ares_tree, np); 154 | _ares_do_callbacks(np); 155 | free(np); 156 | ares_qcnt--; 157 | } 158 | } 159 | 160 | static void 161 | _ares_timeout(int fd, short event, void *arg) 162 | { 163 | struct ares_node *np = (struct ares_node *)arg; 164 | 165 | /* See if we've exceeded max retries for this query. */ 166 | if (++np->retries >= _res.retry) { 167 | RB_REMOVE(ares_tree, &ares_tree, np); 168 | _ares_do_callbacks(np); 169 | free(np); 170 | ares_qcnt--; 171 | } else { 172 | /* Reschedule our query. */ 173 | _ares_send(-1, 0, np); 174 | event_add(&np->ev, &np->tv); 175 | } 176 | } 177 | 178 | static void 179 | _ares_recv(int fd, short event, void *arg) 180 | { 181 | struct ares_node *np, find; 182 | union ares_pkt pkt; 183 | u_char *p, *msg, *eom, dname[MAXDNAME + 1]; 184 | int i, len; 185 | u_int u[4]; 186 | 187 | if (event == EV_TIMEOUT) 188 | return; 189 | 190 | event_add(&ares_ev, &ares_tv); 191 | 192 | len = recv(fd, &pkt.buf, sizeof(pkt.buf), 0); 193 | 194 | /* Parse the question being answered. */ 195 | if (len < HFIXEDSZ || len > PACKETSZ) 196 | return; 197 | 198 | pkt.hdr.qdcount = ntohs(pkt.hdr.qdcount); 199 | pkt.hdr.ancount = ntohs(pkt.hdr.ancount); 200 | msg = pkt.buf; 201 | p = pkt.buf + HFIXEDSZ; 202 | eom = pkt.buf + len; 203 | 204 | if (pkt.hdr.qdcount != 1 || 205 | (i = dn_expand(msg, eom, p, dname, sizeof(dname))) < 0) 206 | return; 207 | 208 | p += i + INT16SZ + INT16SZ; /* skip type, class */ 209 | 210 | if (sscanf(dname, "%d.%d.%d.%d.in-addr.arpa", 211 | &u[3], &u[2], &u[1], &u[0]) != 4) 212 | return; 213 | 214 | find.ip = htonl((u[0] << 24) | (u[1] << 16) | (u[2] << 8) | u[3]); 215 | 216 | /* Find matching query, disable its timeout. */ 217 | if ((np = RB_FIND(ares_tree, &ares_tree, &find)) == NULL || 218 | pkt.hdr.id != np->qid) 219 | return; 220 | 221 | event_del(&np->ev); 222 | np->done = 1; 223 | 224 | /* Parse the answer. */ 225 | while (pkt.hdr.rcode == 0 && pkt.hdr.ancount-- > 0 && p < eom) { 226 | u_short type, class, dlen; 227 | 228 | if ((i = dn_expand(msg, eom, p, dname, sizeof(dname))) < 0) 229 | break; 230 | p += i; 231 | GETSHORT(type, p); 232 | GETSHORT(class, p); 233 | p += INT32SZ; /* skip ttl */ 234 | GETSHORT(dlen, p); 235 | 236 | if (type == T_PTR && class == C_IN) { 237 | i = dn_expand(msg, eom, p, np->name, sizeof(np->name)); 238 | if (i < 0 || i != dlen) 239 | warnx("expand error in PTR name"); 240 | break; 241 | } 242 | p += dlen; 243 | } 244 | /* Execute callbacks. */ 245 | _ares_do_callbacks(np); 246 | #if 0 247 | if (np->retries) 248 | printf("%d retries\n", np->retries); 249 | #endif 250 | if (--ares_qcnt == 0) 251 | event_del(&ares_ev); 252 | } 253 | 254 | int 255 | ares_open(void) 256 | { 257 | int i; 258 | 259 | if (res_init() < 0 || _res.nscount == 0) 260 | return (-1); 261 | 262 | if ((ares_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 263 | return (-1); 264 | 265 | i = 200 * BUFSIZ; 266 | setsockopt(ares_fd, SOL_SOCKET, SO_SNDBUF, &i, sizeof(i)); 267 | i = 200 * BUFSIZ; 268 | setsockopt(ares_fd, SOL_SOCKET, SO_RCVBUF, &i, sizeof(i)); 269 | 270 | event_set(&ares_ev, ares_fd, EV_READ, _ares_recv, &ares_ev); 271 | 272 | RB_INIT(&ares_tree); 273 | ares_qcnt = 0; 274 | 275 | return (0); 276 | } 277 | 278 | int 279 | ares_query(uint32_t ip, ares_callback callback, void *arg) 280 | { 281 | struct ares_node *np, find; 282 | 283 | find.ip = ip; 284 | 285 | /* Check our cache first for the answer. */ 286 | if ((np = RB_FIND(ares_tree, &ares_tree, &find)) != NULL) { 287 | if (!np->done) { 288 | if (_ares_add_callback(np, callback, arg) < 0) 289 | return (-1); 290 | } else 291 | callback(np->ip, np->name, arg); 292 | } else { 293 | if ((np = calloc(1, sizeof(*np))) == NULL) 294 | return (-1); 295 | 296 | /* Create and schedule new query. */ 297 | np->ip = ip; 298 | TAILQ_INIT(&np->callbacks); 299 | if (_ares_add_callback(np, callback, arg) < 0) { 300 | free(np); 301 | return (-1); 302 | } 303 | np->tv.tv_usec = getpid() % 1000000; 304 | 305 | event_set(&np->ev, -1, 0, _ares_send, np); 306 | event_add(&np->ev, &np->tv); 307 | 308 | RB_INSERT(ares_tree, &ares_tree, np); 309 | ares_qcnt++; 310 | } 311 | return (0); 312 | } 313 | 314 | void 315 | ares_close(void) 316 | { 317 | struct ares_node *np, *next; 318 | 319 | for (np = RB_MIN(ares_tree, &ares_tree); np != NULL; np = next) { 320 | next = RB_NEXT(ares_tree, &ares_tree, np); 321 | if (!np->done) { 322 | _ares_do_callbacks(np); 323 | event_del(&np->ev); 324 | } 325 | free(np); 326 | } 327 | RB_INIT(&ares_tree); 328 | 329 | if (ares_fd > 0) { 330 | event_del(&ares_ev); 331 | close(ares_fd); 332 | ares_fd = -1; 333 | } 334 | } 335 | -------------------------------------------------------------------------------- /aclocal.m4: -------------------------------------------------------------------------------- 1 | dnl aclocal.m4 generated automatically by aclocal 1.4-p6 2 | 3 | dnl Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. 4 | dnl This file is free software; the Free Software Foundation 5 | dnl gives unlimited permission to copy and/or distribute it, 6 | dnl with or without modifications, as long as this notice is preserved. 7 | 8 | dnl This program is distributed in the hope that it will be useful, 9 | dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without 10 | dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A 11 | dnl PARTICULAR PURPOSE. 12 | 13 | dnl 14 | dnl Check for 4.4 BSD sa_len member in sockaddr struct 15 | dnl 16 | dnl usage: AC_DNET_SOCKADDR_SA_LEN 17 | dnl results: HAVE_SOCKADDR_SA_LEN (defined) 18 | dnl 19 | AC_DEFUN(AC_DNET_SOCKADDR_SA_LEN, 20 | [AC_MSG_CHECKING(for sa_len in sockaddr struct) 21 | AC_CACHE_VAL(ac_cv_dnet_sockaddr_has_sa_len, 22 | AC_TRY_COMPILE([ 23 | # include 24 | # include ], 25 | [u_int i = sizeof(((struct sockaddr *)0)->sa_len)], 26 | ac_cv_dnet_sockaddr_has_sa_len=yes, 27 | ac_cv_dnet_sockaddr_has_sa_len=no)) 28 | AC_MSG_RESULT($ac_cv_dnet_sockaddr_has_sa_len) 29 | if test $ac_cv_dnet_sockaddr_has_sa_len = yes ; then 30 | AC_DEFINE(HAVE_SOCKADDR_SA_LEN, 1, 31 | [Define if sockaddr struct has sa_len.]) 32 | fi]) 33 | 34 | dnl 35 | dnl AC_LBL_LIBRARY_NET 36 | dnl 37 | dnl This test is for network applications that need socket() and 38 | dnl gethostbyname() -ish functions. Under Solaris, those applications 39 | dnl need to link with "-lsocket -lnsl". Under IRIX, they need to link 40 | dnl with "-lnsl" but should *not* link with "-lsocket" because 41 | dnl libsocket.a breaks a number of things (for instance: 42 | dnl gethostbyname() under IRIX 5.2, and snoop sockets under most 43 | dnl versions of IRIX). 44 | dnl 45 | dnl Unfortunately, many application developers are not aware of this, 46 | dnl and mistakenly write tests that cause -lsocket to be used under 47 | dnl IRIX. It is also easy to write tests that cause -lnsl to be used 48 | dnl under operating systems where neither are necessary (or useful), 49 | dnl such as SunOS 4.1.4, which uses -lnsl for TLI. 50 | dnl 51 | dnl This test exists so that every application developer does not test 52 | dnl this in a different, and subtly broken fashion. 53 | 54 | dnl It has been argued that this test should be broken up into two 55 | dnl seperate tests, one for the resolver libraries, and one for the 56 | dnl libraries necessary for using Sockets API. Unfortunately, the two 57 | dnl are carefully intertwined and allowing the autoconf user to use 58 | dnl them independantly potentially results in unfortunate ordering 59 | dnl dependancies -- as such, such component macros would have to 60 | dnl carefully use indirection and be aware if the other components were 61 | dnl executed. Since other autoconf macros do not go to this trouble, 62 | dnl and almost no applications use sockets without the resolver, this 63 | dnl complexity has not been implemented. 64 | dnl 65 | dnl The check for libresolv is in case you are attempting to link 66 | dnl statically and happen to have a libresolv.a lying around (and no 67 | dnl libnsl.a). 68 | dnl 69 | AC_DEFUN(AC_LBL_LIBRARY_NET, [ 70 | # Most operating systems have gethostbyname() in the default searched 71 | # libraries (i.e. libc): 72 | AC_CHECK_FUNC(gethostbyname, , 73 | # Some OSes (eg. Solaris) place it in libnsl: 74 | AC_CHECK_LIB(nsl, gethostbyname, , 75 | # Some strange OSes (SINIX) have it in libsocket: 76 | AC_CHECK_LIB(socket, gethostbyname, , 77 | # Unfortunately libsocket sometimes depends on libnsl. 78 | # AC_CHECK_LIB's API is essentially broken so the 79 | # following ugliness is necessary: 80 | AC_CHECK_LIB(socket, gethostbyname, 81 | LIBS="-lsocket -lnsl $LIBS", 82 | AC_CHECK_LIB(resolv, gethostbyname), 83 | -lnsl)))) 84 | AC_CHECK_FUNC(socket, , AC_CHECK_LIB(socket, socket, , 85 | AC_CHECK_LIB(socket, socket, LIBS="-lsocket -lnsl $LIBS", , 86 | -lnsl))) 87 | # DLPI needs putmsg under HPUX so test for -lstr while we're at it 88 | AC_CHECK_LIB(str, putmsg) 89 | ]) 90 | 91 | # Do all the work for Automake. This macro actually does too much -- 92 | # some checks are only needed if your package does certain things. 93 | # But this isn't really a big deal. 94 | 95 | # serial 1 96 | 97 | dnl Usage: 98 | dnl AM_INIT_AUTOMAKE(package,version, [no-define]) 99 | 100 | AC_DEFUN([AM_INIT_AUTOMAKE], 101 | [AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl 102 | AC_REQUIRE([AC_PROG_INSTALL]) 103 | PACKAGE=[$1] 104 | AC_SUBST(PACKAGE) 105 | VERSION=[$2] 106 | AC_SUBST(VERSION) 107 | dnl test to see if srcdir already configured 108 | if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then 109 | AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) 110 | fi 111 | ifelse([$3],, 112 | AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) 113 | AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])) 114 | AC_REQUIRE([AM_SANITY_CHECK]) 115 | AC_REQUIRE([AC_ARG_PROGRAM]) 116 | dnl FIXME This is truly gross. 117 | missing_dir=`cd $ac_aux_dir && pwd` 118 | AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}, $missing_dir) 119 | AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) 120 | AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}, $missing_dir) 121 | AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) 122 | AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) 123 | AC_REQUIRE([AC_PROG_MAKE_SET])]) 124 | 125 | # Copyright 2002 Free Software Foundation, Inc. 126 | 127 | # This program is free software; you can redistribute it and/or modify 128 | # it under the terms of the GNU General Public License as published by 129 | # the Free Software Foundation; either version 2, or (at your option) 130 | # any later version. 131 | 132 | # This program is distributed in the hope that it will be useful, 133 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 134 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 135 | # GNU General Public License for more details. 136 | 137 | # You should have received a copy of the GNU General Public License 138 | # along with this program; if not, write to the Free Software 139 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 140 | 141 | # AM_AUTOMAKE_VERSION(VERSION) 142 | # ---------------------------- 143 | # Automake X.Y traces this macro to ensure aclocal.m4 has been 144 | # generated from the m4 files accompanying Automake X.Y. 145 | AC_DEFUN([AM_AUTOMAKE_VERSION],[am__api_version="1.4"]) 146 | 147 | # AM_SET_CURRENT_AUTOMAKE_VERSION 148 | # ------------------------------- 149 | # Call AM_AUTOMAKE_VERSION so it can be traced. 150 | # This function is AC_REQUIREd by AC_INIT_AUTOMAKE. 151 | AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], 152 | [AM_AUTOMAKE_VERSION([1.4-p6])]) 153 | 154 | # 155 | # Check to make sure that the build environment is sane. 156 | # 157 | 158 | AC_DEFUN([AM_SANITY_CHECK], 159 | [AC_MSG_CHECKING([whether build environment is sane]) 160 | # Just in case 161 | sleep 1 162 | echo timestamp > conftestfile 163 | # Do `set' in a subshell so we don't clobber the current shell's 164 | # arguments. Must try -L first in case configure is actually a 165 | # symlink; some systems play weird games with the mod time of symlinks 166 | # (eg FreeBSD returns the mod time of the symlink's containing 167 | # directory). 168 | if ( 169 | set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` 170 | if test "[$]*" = "X"; then 171 | # -L didn't work. 172 | set X `ls -t $srcdir/configure conftestfile` 173 | fi 174 | if test "[$]*" != "X $srcdir/configure conftestfile" \ 175 | && test "[$]*" != "X conftestfile $srcdir/configure"; then 176 | 177 | # If neither matched, then we have a broken ls. This can happen 178 | # if, for instance, CONFIG_SHELL is bash and it inherits a 179 | # broken ls alias from the environment. This has actually 180 | # happened. Such a system could not be considered "sane". 181 | AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken 182 | alias in your environment]) 183 | fi 184 | 185 | test "[$]2" = conftestfile 186 | ) 187 | then 188 | # Ok. 189 | : 190 | else 191 | AC_MSG_ERROR([newly created file is older than distributed files! 192 | Check your system clock]) 193 | fi 194 | rm -f conftest* 195 | AC_MSG_RESULT(yes)]) 196 | 197 | dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY) 198 | dnl The program must properly implement --version. 199 | AC_DEFUN([AM_MISSING_PROG], 200 | [AC_MSG_CHECKING(for working $2) 201 | # Run test in a subshell; some versions of sh will print an error if 202 | # an executable is not found, even if stderr is redirected. 203 | # Redirect stdin to placate older versions of autoconf. Sigh. 204 | if ($2 --version) < /dev/null > /dev/null 2>&1; then 205 | $1=$2 206 | AC_MSG_RESULT(found) 207 | else 208 | $1="$3/missing $2" 209 | AC_MSG_RESULT(missing) 210 | fi 211 | AC_SUBST($1)]) 212 | 213 | # Like AC_CONFIG_HEADER, but automatically create stamp file. 214 | 215 | AC_DEFUN([AM_CONFIG_HEADER], 216 | [AC_PREREQ([2.12]) 217 | AC_CONFIG_HEADER([$1]) 218 | dnl When config.status generates a header, we must update the stamp-h file. 219 | dnl This file resides in the same directory as the config header 220 | dnl that is generated. We must strip everything past the first ":", 221 | dnl and everything past the last "/". 222 | AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl 223 | ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>, 224 | <>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>, 225 | <>; do 227 | case " <<$>>CONFIG_HEADERS " in 228 | *" <<$>>am_file "*<<)>> 229 | echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx 230 | ;; 231 | esac 232 | am_indx=`expr "<<$>>am_indx" + 1` 233 | done<<>>dnl>>) 234 | changequote([,]))]) 235 | 236 | -------------------------------------------------------------------------------- /Makefile.in: -------------------------------------------------------------------------------- 1 | # Makefile.in generated automatically by automake 1.4-p6 from Makefile.am 2 | 3 | # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. 4 | # This Makefile.in is free software; the Free Software Foundation 5 | # gives unlimited permission to copy and/or distribute it, 6 | # with or without modifications, as long as this notice is preserved. 7 | 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY, to the extent permitted by law; without 10 | # even the implied warranty of MERCHANTABILITY or FITNESS FOR A 11 | # PARTICULAR PURPOSE. 12 | 13 | 14 | SHELL = @SHELL@ 15 | 16 | srcdir = @srcdir@ 17 | top_srcdir = @top_srcdir@ 18 | VPATH = @srcdir@ 19 | prefix = @prefix@ 20 | exec_prefix = @exec_prefix@ 21 | 22 | bindir = @bindir@ 23 | sbindir = @sbindir@ 24 | libexecdir = @libexecdir@ 25 | datadir = @datadir@ 26 | sysconfdir = @sysconfdir@ 27 | sharedstatedir = @sharedstatedir@ 28 | localstatedir = @localstatedir@ 29 | libdir = @libdir@ 30 | infodir = @infodir@ 31 | mandir = @mandir@ 32 | includedir = @includedir@ 33 | oldincludedir = /usr/include 34 | 35 | DESTDIR = 36 | 37 | pkgdatadir = $(datadir)/@PACKAGE@ 38 | pkglibdir = $(libdir)/@PACKAGE@ 39 | pkgincludedir = $(includedir)/@PACKAGE@ 40 | 41 | top_builddir = . 42 | 43 | ACLOCAL = @ACLOCAL@ 44 | AUTOCONF = @AUTOCONF@ 45 | AUTOMAKE = @AUTOMAKE@ 46 | AUTOHEADER = @AUTOHEADER@ 47 | 48 | INSTALL = @INSTALL@ 49 | INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) 50 | INSTALL_DATA = @INSTALL_DATA@ 51 | INSTALL_SCRIPT = @INSTALL_SCRIPT@ 52 | transform = @program_transform_name@ 53 | 54 | NORMAL_INSTALL = : 55 | PRE_INSTALL = : 56 | POST_INSTALL = : 57 | NORMAL_UNINSTALL = : 58 | PRE_UNINSTALL = : 59 | POST_UNINSTALL = : 60 | AWK = @AWK@ 61 | CC = @CC@ 62 | DNETINC = @DNETINC@ 63 | DNETLIB = @DNETLIB@ 64 | EVENTINC = @EVENTINC@ 65 | EVENTLIB = @EVENTLIB@ 66 | LN_S = @LN_S@ 67 | MAKEINFO = @MAKEINFO@ 68 | PACKAGE = @PACKAGE@ 69 | PCAPINC = @PCAPINC@ 70 | PCAPLIB = @PCAPLIB@ 71 | VERSION = @VERSION@ 72 | 73 | AUTOMAKE_OPTIONS = foreign no-dependencies 74 | 75 | INCLUDES = @PCAPINC@ @EVENTINC@ @DNETINC@ -I$(top_srcdir)/compat 76 | 77 | LDADD = @LIBOBJS@ @PCAPLIB@ @EVENTLIB@ @DNETLIB@ 78 | 79 | sbin_PROGRAMS = dscan 80 | 81 | dscan_SOURCES = ares.c ares.h bag.c bag.h dscan-int.h dscan.c dscan.h hash.c hash.h main.c mysignal.c mysignal.h ndb.c ndb.h osstack.c osstack.h parse.c parse.h pcaputil.c pcaputil.h print.c print.h recv.c scan.c 82 | 83 | 84 | man_MANS = dscan.8 85 | 86 | EXTRA_DIST = LICENSE config/install-sh config/missing config/mkinstalldirs compat/strsep.c compat/sys/queue.h compat/sys/tree.h ahost.c bag-test.c $(man_MANS) 87 | 88 | 89 | DISTCLEANFILES = *~ 90 | ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 91 | mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs 92 | CONFIG_HEADER = config.h 93 | CONFIG_CLEAN_FILES = 94 | PROGRAMS = $(sbin_PROGRAMS) 95 | 96 | 97 | DEFS = @DEFS@ -I. -I$(srcdir) -I. 98 | CPPFLAGS = @CPPFLAGS@ 99 | LDFLAGS = @LDFLAGS@ 100 | LIBS = @LIBS@ 101 | dscan_OBJECTS = ares.o bag.o dscan.o hash.o main.o mysignal.o ndb.o \ 102 | osstack.o parse.o pcaputil.o print.o recv.o scan.o 103 | dscan_LDADD = $(LDADD) 104 | dscan_DEPENDENCIES = @LIBOBJS@ 105 | dscan_LDFLAGS = 106 | CFLAGS = @CFLAGS@ 107 | COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) 108 | CCLD = $(CC) 109 | LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ 110 | man8dir = $(mandir)/man8 111 | MANS = $(man_MANS) 112 | 113 | NROFF = nroff 114 | DIST_COMMON = ./stamp-h.in Makefile.am Makefile.in acconfig.h \ 115 | acinclude.m4 aclocal.m4 config.h.in configure configure.ac 116 | 117 | 118 | DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) 119 | 120 | TAR = tar 121 | GZIP_ENV = --best 122 | SOURCES = $(dscan_SOURCES) 123 | OBJECTS = $(dscan_OBJECTS) 124 | 125 | all: all-redirect 126 | .SUFFIXES: 127 | .SUFFIXES: .S .c .o .s 128 | $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) 129 | cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile 130 | 131 | Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status 132 | cd $(top_builddir) \ 133 | && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status 134 | 135 | $(ACLOCAL_M4): configure.ac acinclude.m4 136 | cd $(srcdir) && $(ACLOCAL) 137 | 138 | config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) 139 | $(SHELL) ./config.status --recheck 140 | $(srcdir)/configure: $(srcdir)/configure.ac $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) 141 | cd $(srcdir) && $(AUTOCONF) 142 | 143 | config.h: stamp-h 144 | @if test ! -f $@; then \ 145 | rm -f stamp-h; \ 146 | $(MAKE) stamp-h; \ 147 | else :; fi 148 | stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status 149 | cd $(top_builddir) \ 150 | && CONFIG_FILES= CONFIG_HEADERS=config.h \ 151 | $(SHELL) ./config.status 152 | @echo timestamp > stamp-h 2> /dev/null 153 | $(srcdir)/config.h.in: $(srcdir)/stamp-h.in 154 | @if test ! -f $@; then \ 155 | rm -f $(srcdir)/stamp-h.in; \ 156 | $(MAKE) $(srcdir)/stamp-h.in; \ 157 | else :; fi 158 | $(srcdir)/stamp-h.in: $(top_srcdir)/configure.ac $(ACLOCAL_M4) acconfig.h 159 | cd $(top_srcdir) && $(AUTOHEADER) 160 | @echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null 161 | 162 | mostlyclean-hdr: 163 | 164 | clean-hdr: 165 | 166 | distclean-hdr: 167 | -rm -f config.h 168 | 169 | maintainer-clean-hdr: 170 | 171 | mostlyclean-sbinPROGRAMS: 172 | 173 | clean-sbinPROGRAMS: 174 | -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) 175 | 176 | distclean-sbinPROGRAMS: 177 | 178 | maintainer-clean-sbinPROGRAMS: 179 | 180 | install-sbinPROGRAMS: $(sbin_PROGRAMS) 181 | @$(NORMAL_INSTALL) 182 | $(mkinstalldirs) $(DESTDIR)$(sbindir) 183 | @list='$(sbin_PROGRAMS)'; for p in $$list; do \ 184 | if test -f $$p; then \ 185 | echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \ 186 | $(INSTALL_PROGRAM) $$p $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ 187 | else :; fi; \ 188 | done 189 | 190 | uninstall-sbinPROGRAMS: 191 | @$(NORMAL_UNINSTALL) 192 | list='$(sbin_PROGRAMS)'; for p in $$list; do \ 193 | rm -f $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ 194 | done 195 | 196 | .c.o: 197 | $(COMPILE) -c $< 198 | 199 | .s.o: 200 | $(COMPILE) -c $< 201 | 202 | .S.o: 203 | $(COMPILE) -c $< 204 | 205 | mostlyclean-compile: 206 | -rm -f *.o core *.core 207 | 208 | clean-compile: 209 | 210 | distclean-compile: 211 | -rm -f *.tab.c 212 | 213 | maintainer-clean-compile: 214 | 215 | dscan: $(dscan_OBJECTS) $(dscan_DEPENDENCIES) 216 | @rm -f dscan 217 | $(LINK) $(dscan_LDFLAGS) $(dscan_OBJECTS) $(dscan_LDADD) $(LIBS) 218 | 219 | install-man8: 220 | $(mkinstalldirs) $(DESTDIR)$(man8dir) 221 | @list='$(man8_MANS)'; \ 222 | l2='$(man_MANS)'; for i in $$l2; do \ 223 | case "$$i" in \ 224 | *.8*) list="$$list $$i" ;; \ 225 | esac; \ 226 | done; \ 227 | for i in $$list; do \ 228 | if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ 229 | else file=$$i; fi; \ 230 | ext=`echo $$i | sed -e 's/^.*\\.//'`; \ 231 | inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ 232 | inst=`echo $$inst | sed '$(transform)'`.$$ext; \ 233 | echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst"; \ 234 | $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst; \ 235 | done 236 | 237 | uninstall-man8: 238 | @list='$(man8_MANS)'; \ 239 | l2='$(man_MANS)'; for i in $$l2; do \ 240 | case "$$i" in \ 241 | *.8*) list="$$list $$i" ;; \ 242 | esac; \ 243 | done; \ 244 | for i in $$list; do \ 245 | ext=`echo $$i | sed -e 's/^.*\\.//'`; \ 246 | inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ 247 | inst=`echo $$inst | sed '$(transform)'`.$$ext; \ 248 | echo " rm -f $(DESTDIR)$(man8dir)/$$inst"; \ 249 | rm -f $(DESTDIR)$(man8dir)/$$inst; \ 250 | done 251 | install-man: $(MANS) 252 | @$(NORMAL_INSTALL) 253 | $(MAKE) $(AM_MAKEFLAGS) install-man8 254 | uninstall-man: 255 | @$(NORMAL_UNINSTALL) 256 | $(MAKE) $(AM_MAKEFLAGS) uninstall-man8 257 | 258 | tags: TAGS 259 | 260 | ID: $(HEADERS) $(SOURCES) $(LISP) 261 | list='$(SOURCES) $(HEADERS)'; \ 262 | unique=`for i in $$list; do echo $$i; done | \ 263 | awk ' { files[$$0] = 1; } \ 264 | END { for (i in files) print i; }'`; \ 265 | here=`pwd` && cd $(srcdir) \ 266 | && mkid -f$$here/ID $$unique $(LISP) 267 | 268 | TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP) 269 | tags=; \ 270 | here=`pwd`; \ 271 | list='$(SOURCES) $(HEADERS)'; \ 272 | unique=`for i in $$list; do echo $$i; done | \ 273 | awk ' { files[$$0] = 1; } \ 274 | END { for (i in files) print i; }'`; \ 275 | test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \ 276 | || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP) -o $$here/TAGS) 277 | 278 | mostlyclean-tags: 279 | 280 | clean-tags: 281 | 282 | distclean-tags: 283 | -rm -f TAGS ID 284 | 285 | maintainer-clean-tags: 286 | 287 | distdir = $(PACKAGE)-$(VERSION) 288 | top_distdir = $(distdir) 289 | 290 | # This target untars the dist file and tries a VPATH configuration. Then 291 | # it guarantees that the distribution is self-contained by making another 292 | # tarfile. 293 | distcheck: dist 294 | -rm -rf $(distdir) 295 | GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz 296 | mkdir $(distdir)/=build 297 | mkdir $(distdir)/=inst 298 | dc_install_base=`cd $(distdir)/=inst && pwd`; \ 299 | cd $(distdir)/=build \ 300 | && ../configure --srcdir=.. --prefix=$$dc_install_base \ 301 | && $(MAKE) $(AM_MAKEFLAGS) \ 302 | && $(MAKE) $(AM_MAKEFLAGS) dvi \ 303 | && $(MAKE) $(AM_MAKEFLAGS) check \ 304 | && $(MAKE) $(AM_MAKEFLAGS) install \ 305 | && $(MAKE) $(AM_MAKEFLAGS) installcheck \ 306 | && $(MAKE) $(AM_MAKEFLAGS) dist 307 | -rm -rf $(distdir) 308 | @banner="$(distdir).tar.gz is ready for distribution"; \ 309 | dashes=`echo "$$banner" | sed s/./=/g`; \ 310 | echo "$$dashes"; \ 311 | echo "$$banner"; \ 312 | echo "$$dashes" 313 | dist: distdir 314 | -chmod -R a+r $(distdir) 315 | GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) 316 | -rm -rf $(distdir) 317 | dist-all: distdir 318 | -chmod -R a+r $(distdir) 319 | GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) 320 | -rm -rf $(distdir) 321 | distdir: $(DISTFILES) 322 | -rm -rf $(distdir) 323 | mkdir $(distdir) 324 | -chmod 777 $(distdir) 325 | $(mkinstalldirs) $(distdir)/compat $(distdir)/compat/sys \ 326 | $(distdir)/config 327 | @for file in $(DISTFILES); do \ 328 | d=$(srcdir); \ 329 | if test -d $$d/$$file; then \ 330 | cp -pr $$d/$$file $(distdir)/$$file; \ 331 | else \ 332 | test -f $(distdir)/$$file \ 333 | || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ 334 | || cp -p $$d/$$file $(distdir)/$$file || :; \ 335 | fi; \ 336 | done 337 | info-am: 338 | info: info-am 339 | dvi-am: 340 | dvi: dvi-am 341 | check-am: all-am 342 | check: check-am 343 | installcheck-am: 344 | installcheck: installcheck-am 345 | all-recursive-am: config.h 346 | $(MAKE) $(AM_MAKEFLAGS) all-recursive 347 | 348 | install-exec-am: install-sbinPROGRAMS 349 | install-exec: install-exec-am 350 | 351 | install-data-am: install-man 352 | install-data: install-data-am 353 | 354 | install-am: all-am 355 | @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am 356 | install: install-am 357 | uninstall-am: uninstall-sbinPROGRAMS uninstall-man 358 | uninstall: uninstall-am 359 | all-am: Makefile $(PROGRAMS) $(MANS) config.h 360 | all-redirect: all-am 361 | install-strip: 362 | $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install 363 | installdirs: 364 | $(mkinstalldirs) $(DESTDIR)$(sbindir) $(DESTDIR)$(mandir)/man8 365 | 366 | 367 | mostlyclean-generic: 368 | 369 | clean-generic: 370 | 371 | distclean-generic: 372 | -rm -f Makefile $(CONFIG_CLEAN_FILES) 373 | -rm -f config.cache config.log stamp-h stamp-h[0-9]* 374 | -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) 375 | 376 | maintainer-clean-generic: 377 | mostlyclean-am: mostlyclean-hdr mostlyclean-sbinPROGRAMS \ 378 | mostlyclean-compile mostlyclean-tags \ 379 | mostlyclean-generic 380 | 381 | mostlyclean: mostlyclean-am 382 | 383 | clean-am: clean-hdr clean-sbinPROGRAMS clean-compile clean-tags \ 384 | clean-generic mostlyclean-am 385 | 386 | clean: clean-am 387 | 388 | distclean-am: distclean-hdr distclean-sbinPROGRAMS distclean-compile \ 389 | distclean-tags distclean-generic clean-am 390 | 391 | distclean: distclean-am 392 | -rm -f config.status 393 | 394 | maintainer-clean-am: maintainer-clean-hdr maintainer-clean-sbinPROGRAMS \ 395 | maintainer-clean-compile maintainer-clean-tags \ 396 | maintainer-clean-generic distclean-am 397 | @echo "This command is intended for maintainers to use;" 398 | @echo "it deletes files that may require special tools to rebuild." 399 | 400 | maintainer-clean: maintainer-clean-am 401 | -rm -f config.status 402 | 403 | .PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \ 404 | mostlyclean-sbinPROGRAMS distclean-sbinPROGRAMS clean-sbinPROGRAMS \ 405 | maintainer-clean-sbinPROGRAMS uninstall-sbinPROGRAMS \ 406 | install-sbinPROGRAMS mostlyclean-compile distclean-compile \ 407 | clean-compile maintainer-clean-compile install-man8 uninstall-man8 \ 408 | install-man uninstall-man tags mostlyclean-tags distclean-tags \ 409 | clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \ 410 | check-am installcheck-am installcheck all-recursive-am install-exec-am \ 411 | install-exec install-data-am install-data install-am install \ 412 | uninstall-am uninstall all-redirect all-am all installdirs \ 413 | mostlyclean-generic distclean-generic clean-generic \ 414 | maintainer-clean-generic clean mostlyclean distclean maintainer-clean 415 | 416 | 417 | dscan.8.txt: dscan.8 418 | groff -t -e -man -Tascii dscan.8 | col -bx > $@ 419 | 420 | strsep.o: $(top_srcdir)/compat/strsep.c 421 | $(COMPILE) -c $< 422 | 423 | ahost: ahost.o ares.o bag.o parse.o 424 | $(LINK) ahost.o ares.o bag.o parse.o $(LDADD) 425 | 426 | bag-test: bag-test.o bag.o parse.o 427 | $(LINK) bag-test.o bag.o parse.o $(LDADD) -ledit -ltermcap 428 | 429 | # Tell versions [3.59,3.63) of GNU make to not export all variables. 430 | # Otherwise a system limit (for SysV at least) may be exceeded. 431 | .NOEXPORT: 432 | -------------------------------------------------------------------------------- /compat/sys/queue.h: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: queue.h,v 1.22 2001/06/23 04:39:35 angelos Exp $ */ 2 | /* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ 3 | 4 | /* 5 | * Copyright (c) 1991, 1993 6 | * The Regents of the University of California. All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions 10 | * are met: 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. All advertising materials mentioning features or use of this software 17 | * must display the following acknowledgement: 18 | * This product includes software developed by the University of 19 | * California, Berkeley and its contributors. 20 | * 4. Neither the name of the University nor the names of its contributors 21 | * may be used to endorse or promote products derived from this software 22 | * without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 | * SUCH DAMAGE. 35 | * 36 | * @(#)queue.h 8.5 (Berkeley) 8/20/94 37 | */ 38 | 39 | #ifndef _SYS_QUEUE_H_ 40 | #define _SYS_QUEUE_H_ 41 | 42 | /* 43 | * This file defines five types of data structures: singly-linked lists, 44 | * lists, simple queues, tail queues, and circular queues. 45 | * 46 | * 47 | * A singly-linked list is headed by a single forward pointer. The elements 48 | * are singly linked for minimum space and pointer manipulation overhead at 49 | * the expense of O(n) removal for arbitrary elements. New elements can be 50 | * added to the list after an existing element or at the head of the list. 51 | * Elements being removed from the head of the list should use the explicit 52 | * macro for this purpose for optimum efficiency. A singly-linked list may 53 | * only be traversed in the forward direction. Singly-linked lists are ideal 54 | * for applications with large datasets and few or no removals or for 55 | * implementing a LIFO queue. 56 | * 57 | * A list is headed by a single forward pointer (or an array of forward 58 | * pointers for a hash table header). The elements are doubly linked 59 | * so that an arbitrary element can be removed without a need to 60 | * traverse the list. New elements can be added to the list before 61 | * or after an existing element or at the head of the list. A list 62 | * may only be traversed in the forward direction. 63 | * 64 | * A simple queue is headed by a pair of pointers, one the head of the 65 | * list and the other to the tail of the list. The elements are singly 66 | * linked to save space, so elements can only be removed from the 67 | * head of the list. New elements can be added to the list before or after 68 | * an existing element, at the head of the list, or at the end of the 69 | * list. A simple queue may only be traversed in the forward direction. 70 | * 71 | * A tail queue is headed by a pair of pointers, one to the head of the 72 | * list and the other to the tail of the list. The elements are doubly 73 | * linked so that an arbitrary element can be removed without a need to 74 | * traverse the list. New elements can be added to the list before or 75 | * after an existing element, at the head of the list, or at the end of 76 | * the list. A tail queue may be traversed in either direction. 77 | * 78 | * A circle queue is headed by a pair of pointers, one to the head of the 79 | * list and the other to the tail of the list. The elements are doubly 80 | * linked so that an arbitrary element can be removed without a need to 81 | * traverse the list. New elements can be added to the list before or after 82 | * an existing element, at the head of the list, or at the end of the list. 83 | * A circle queue may be traversed in either direction, but has a more 84 | * complex end of list detection. 85 | * 86 | * For details on the use of these macros, see the queue(3) manual page. 87 | */ 88 | 89 | /* 90 | * Singly-linked List definitions. 91 | */ 92 | #define SLIST_HEAD(name, type) \ 93 | struct name { \ 94 | struct type *slh_first; /* first element */ \ 95 | } 96 | 97 | #define SLIST_HEAD_INITIALIZER(head) \ 98 | { NULL } 99 | 100 | #define SLIST_ENTRY(type) \ 101 | struct { \ 102 | struct type *sle_next; /* next element */ \ 103 | } 104 | 105 | /* 106 | * Singly-linked List access methods. 107 | */ 108 | #define SLIST_FIRST(head) ((head)->slh_first) 109 | #define SLIST_END(head) NULL 110 | #define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) 111 | #define SLIST_NEXT(elm, field) ((elm)->field.sle_next) 112 | 113 | #define SLIST_FOREACH(var, head, field) \ 114 | for((var) = SLIST_FIRST(head); \ 115 | (var) != SLIST_END(head); \ 116 | (var) = SLIST_NEXT(var, field)) 117 | 118 | /* 119 | * Singly-linked List functions. 120 | */ 121 | #define SLIST_INIT(head) { \ 122 | SLIST_FIRST(head) = SLIST_END(head); \ 123 | } 124 | 125 | #define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ 126 | (elm)->field.sle_next = (slistelm)->field.sle_next; \ 127 | (slistelm)->field.sle_next = (elm); \ 128 | } while (0) 129 | 130 | #define SLIST_INSERT_HEAD(head, elm, field) do { \ 131 | (elm)->field.sle_next = (head)->slh_first; \ 132 | (head)->slh_first = (elm); \ 133 | } while (0) 134 | 135 | #define SLIST_REMOVE_HEAD(head, field) do { \ 136 | (head)->slh_first = (head)->slh_first->field.sle_next; \ 137 | } while (0) 138 | 139 | #define SLIST_REMOVE(head, elm, type, field) do { \ 140 | if ((head)->slh_first == (elm)) { \ 141 | SLIST_REMOVE_HEAD((head), field); \ 142 | } \ 143 | else { \ 144 | struct type *curelm = (head)->slh_first; \ 145 | while( curelm->field.sle_next != (elm) ) \ 146 | curelm = curelm->field.sle_next; \ 147 | curelm->field.sle_next = \ 148 | curelm->field.sle_next->field.sle_next; \ 149 | } \ 150 | } while (0) 151 | 152 | /* 153 | * List definitions. 154 | */ 155 | #define LIST_HEAD(name, type) \ 156 | struct name { \ 157 | struct type *lh_first; /* first element */ \ 158 | } 159 | 160 | #define LIST_HEAD_INITIALIZER(head) \ 161 | { NULL } 162 | 163 | #define LIST_ENTRY(type) \ 164 | struct { \ 165 | struct type *le_next; /* next element */ \ 166 | struct type **le_prev; /* address of previous next element */ \ 167 | } 168 | 169 | /* 170 | * List access methods 171 | */ 172 | #define LIST_FIRST(head) ((head)->lh_first) 173 | #define LIST_END(head) NULL 174 | #define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) 175 | #define LIST_NEXT(elm, field) ((elm)->field.le_next) 176 | 177 | #define LIST_FOREACH(var, head, field) \ 178 | for((var) = LIST_FIRST(head); \ 179 | (var)!= LIST_END(head); \ 180 | (var) = LIST_NEXT(var, field)) 181 | 182 | /* 183 | * List functions. 184 | */ 185 | #define LIST_INIT(head) do { \ 186 | LIST_FIRST(head) = LIST_END(head); \ 187 | } while (0) 188 | 189 | #define LIST_INSERT_AFTER(listelm, elm, field) do { \ 190 | if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ 191 | (listelm)->field.le_next->field.le_prev = \ 192 | &(elm)->field.le_next; \ 193 | (listelm)->field.le_next = (elm); \ 194 | (elm)->field.le_prev = &(listelm)->field.le_next; \ 195 | } while (0) 196 | 197 | #define LIST_INSERT_BEFORE(listelm, elm, field) do { \ 198 | (elm)->field.le_prev = (listelm)->field.le_prev; \ 199 | (elm)->field.le_next = (listelm); \ 200 | *(listelm)->field.le_prev = (elm); \ 201 | (listelm)->field.le_prev = &(elm)->field.le_next; \ 202 | } while (0) 203 | 204 | #define LIST_INSERT_HEAD(head, elm, field) do { \ 205 | if (((elm)->field.le_next = (head)->lh_first) != NULL) \ 206 | (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ 207 | (head)->lh_first = (elm); \ 208 | (elm)->field.le_prev = &(head)->lh_first; \ 209 | } while (0) 210 | 211 | #define LIST_REMOVE(elm, field) do { \ 212 | if ((elm)->field.le_next != NULL) \ 213 | (elm)->field.le_next->field.le_prev = \ 214 | (elm)->field.le_prev; \ 215 | *(elm)->field.le_prev = (elm)->field.le_next; \ 216 | } while (0) 217 | 218 | #define LIST_REPLACE(elm, elm2, field) do { \ 219 | if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ 220 | (elm2)->field.le_next->field.le_prev = \ 221 | &(elm2)->field.le_next; \ 222 | (elm2)->field.le_prev = (elm)->field.le_prev; \ 223 | *(elm2)->field.le_prev = (elm2); \ 224 | } while (0) 225 | 226 | /* 227 | * Simple queue definitions. 228 | */ 229 | #define SIMPLEQ_HEAD(name, type) \ 230 | struct name { \ 231 | struct type *sqh_first; /* first element */ \ 232 | struct type **sqh_last; /* addr of last next element */ \ 233 | } 234 | 235 | #define SIMPLEQ_HEAD_INITIALIZER(head) \ 236 | { NULL, &(head).sqh_first } 237 | 238 | #define SIMPLEQ_ENTRY(type) \ 239 | struct { \ 240 | struct type *sqe_next; /* next element */ \ 241 | } 242 | 243 | /* 244 | * Simple queue access methods. 245 | */ 246 | #define SIMPLEQ_FIRST(head) ((head)->sqh_first) 247 | #define SIMPLEQ_END(head) NULL 248 | #define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) 249 | #define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) 250 | 251 | #define SIMPLEQ_FOREACH(var, head, field) \ 252 | for((var) = SIMPLEQ_FIRST(head); \ 253 | (var) != SIMPLEQ_END(head); \ 254 | (var) = SIMPLEQ_NEXT(var, field)) 255 | 256 | /* 257 | * Simple queue functions. 258 | */ 259 | #define SIMPLEQ_INIT(head) do { \ 260 | (head)->sqh_first = NULL; \ 261 | (head)->sqh_last = &(head)->sqh_first; \ 262 | } while (0) 263 | 264 | #define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ 265 | if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ 266 | (head)->sqh_last = &(elm)->field.sqe_next; \ 267 | (head)->sqh_first = (elm); \ 268 | } while (0) 269 | 270 | #define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ 271 | (elm)->field.sqe_next = NULL; \ 272 | *(head)->sqh_last = (elm); \ 273 | (head)->sqh_last = &(elm)->field.sqe_next; \ 274 | } while (0) 275 | 276 | #define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ 277 | if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ 278 | (head)->sqh_last = &(elm)->field.sqe_next; \ 279 | (listelm)->field.sqe_next = (elm); \ 280 | } while (0) 281 | 282 | #define SIMPLEQ_REMOVE_HEAD(head, elm, field) do { \ 283 | if (((head)->sqh_first = (elm)->field.sqe_next) == NULL) \ 284 | (head)->sqh_last = &(head)->sqh_first; \ 285 | } while (0) 286 | 287 | /* 288 | * Tail queue definitions. 289 | */ 290 | #define TAILQ_HEAD(name, type) \ 291 | struct name { \ 292 | struct type *tqh_first; /* first element */ \ 293 | struct type **tqh_last; /* addr of last next element */ \ 294 | } 295 | 296 | #define TAILQ_HEAD_INITIALIZER(head) \ 297 | { NULL, &(head).tqh_first } 298 | 299 | #define TAILQ_ENTRY(type) \ 300 | struct { \ 301 | struct type *tqe_next; /* next element */ \ 302 | struct type **tqe_prev; /* address of previous next element */ \ 303 | } 304 | 305 | /* 306 | * tail queue access methods 307 | */ 308 | #define TAILQ_FIRST(head) ((head)->tqh_first) 309 | #define TAILQ_END(head) NULL 310 | #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) 311 | #define TAILQ_LAST(head, headname) \ 312 | (*(((struct headname *)((head)->tqh_last))->tqh_last)) 313 | /* XXX */ 314 | #define TAILQ_PREV(elm, headname, field) \ 315 | (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) 316 | #define TAILQ_EMPTY(head) \ 317 | (TAILQ_FIRST(head) == TAILQ_END(head)) 318 | 319 | #define TAILQ_FOREACH(var, head, field) \ 320 | for((var) = TAILQ_FIRST(head); \ 321 | (var) != TAILQ_END(head); \ 322 | (var) = TAILQ_NEXT(var, field)) 323 | 324 | #define TAILQ_FOREACH_REVERSE(var, head, field, headname) \ 325 | for((var) = TAILQ_LAST(head, headname); \ 326 | (var) != TAILQ_END(head); \ 327 | (var) = TAILQ_PREV(var, headname, field)) 328 | 329 | /* 330 | * Tail queue functions. 331 | */ 332 | #define TAILQ_INIT(head) do { \ 333 | (head)->tqh_first = NULL; \ 334 | (head)->tqh_last = &(head)->tqh_first; \ 335 | } while (0) 336 | 337 | #define TAILQ_INSERT_HEAD(head, elm, field) do { \ 338 | if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ 339 | (head)->tqh_first->field.tqe_prev = \ 340 | &(elm)->field.tqe_next; \ 341 | else \ 342 | (head)->tqh_last = &(elm)->field.tqe_next; \ 343 | (head)->tqh_first = (elm); \ 344 | (elm)->field.tqe_prev = &(head)->tqh_first; \ 345 | } while (0) 346 | 347 | #define TAILQ_INSERT_TAIL(head, elm, field) do { \ 348 | (elm)->field.tqe_next = NULL; \ 349 | (elm)->field.tqe_prev = (head)->tqh_last; \ 350 | *(head)->tqh_last = (elm); \ 351 | (head)->tqh_last = &(elm)->field.tqe_next; \ 352 | } while (0) 353 | 354 | #define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ 355 | if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ 356 | (elm)->field.tqe_next->field.tqe_prev = \ 357 | &(elm)->field.tqe_next; \ 358 | else \ 359 | (head)->tqh_last = &(elm)->field.tqe_next; \ 360 | (listelm)->field.tqe_next = (elm); \ 361 | (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ 362 | } while (0) 363 | 364 | #define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ 365 | (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ 366 | (elm)->field.tqe_next = (listelm); \ 367 | *(listelm)->field.tqe_prev = (elm); \ 368 | (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ 369 | } while (0) 370 | 371 | #define TAILQ_REMOVE(head, elm, field) do { \ 372 | if (((elm)->field.tqe_next) != NULL) \ 373 | (elm)->field.tqe_next->field.tqe_prev = \ 374 | (elm)->field.tqe_prev; \ 375 | else \ 376 | (head)->tqh_last = (elm)->field.tqe_prev; \ 377 | *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ 378 | } while (0) 379 | 380 | #define TAILQ_REPLACE(head, elm, elm2, field) do { \ 381 | if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ 382 | (elm2)->field.tqe_next->field.tqe_prev = \ 383 | &(elm2)->field.tqe_next; \ 384 | else \ 385 | (head)->tqh_last = &(elm2)->field.tqe_next; \ 386 | (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ 387 | *(elm2)->field.tqe_prev = (elm2); \ 388 | } while (0) 389 | 390 | /* 391 | * Circular queue definitions. 392 | */ 393 | #define CIRCLEQ_HEAD(name, type) \ 394 | struct name { \ 395 | struct type *cqh_first; /* first element */ \ 396 | struct type *cqh_last; /* last element */ \ 397 | } 398 | 399 | #define CIRCLEQ_HEAD_INITIALIZER(head) \ 400 | { CIRCLEQ_END(&head), CIRCLEQ_END(&head) } 401 | 402 | #define CIRCLEQ_ENTRY(type) \ 403 | struct { \ 404 | struct type *cqe_next; /* next element */ \ 405 | struct type *cqe_prev; /* previous element */ \ 406 | } 407 | 408 | /* 409 | * Circular queue access methods 410 | */ 411 | #define CIRCLEQ_FIRST(head) ((head)->cqh_first) 412 | #define CIRCLEQ_LAST(head) ((head)->cqh_last) 413 | #define CIRCLEQ_END(head) ((void *)(head)) 414 | #define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) 415 | #define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) 416 | #define CIRCLEQ_EMPTY(head) \ 417 | (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head)) 418 | 419 | #define CIRCLEQ_FOREACH(var, head, field) \ 420 | for((var) = CIRCLEQ_FIRST(head); \ 421 | (var) != CIRCLEQ_END(head); \ 422 | (var) = CIRCLEQ_NEXT(var, field)) 423 | 424 | #define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ 425 | for((var) = CIRCLEQ_LAST(head); \ 426 | (var) != CIRCLEQ_END(head); \ 427 | (var) = CIRCLEQ_PREV(var, field)) 428 | 429 | /* 430 | * Circular queue functions. 431 | */ 432 | #define CIRCLEQ_INIT(head) do { \ 433 | (head)->cqh_first = CIRCLEQ_END(head); \ 434 | (head)->cqh_last = CIRCLEQ_END(head); \ 435 | } while (0) 436 | 437 | #define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ 438 | (elm)->field.cqe_next = (listelm)->field.cqe_next; \ 439 | (elm)->field.cqe_prev = (listelm); \ 440 | if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \ 441 | (head)->cqh_last = (elm); \ 442 | else \ 443 | (listelm)->field.cqe_next->field.cqe_prev = (elm); \ 444 | (listelm)->field.cqe_next = (elm); \ 445 | } while (0) 446 | 447 | #define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ 448 | (elm)->field.cqe_next = (listelm); \ 449 | (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ 450 | if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \ 451 | (head)->cqh_first = (elm); \ 452 | else \ 453 | (listelm)->field.cqe_prev->field.cqe_next = (elm); \ 454 | (listelm)->field.cqe_prev = (elm); \ 455 | } while (0) 456 | 457 | #define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ 458 | (elm)->field.cqe_next = (head)->cqh_first; \ 459 | (elm)->field.cqe_prev = CIRCLEQ_END(head); \ 460 | if ((head)->cqh_last == CIRCLEQ_END(head)) \ 461 | (head)->cqh_last = (elm); \ 462 | else \ 463 | (head)->cqh_first->field.cqe_prev = (elm); \ 464 | (head)->cqh_first = (elm); \ 465 | } while (0) 466 | 467 | #define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ 468 | (elm)->field.cqe_next = CIRCLEQ_END(head); \ 469 | (elm)->field.cqe_prev = (head)->cqh_last; \ 470 | if ((head)->cqh_first == CIRCLEQ_END(head)) \ 471 | (head)->cqh_first = (elm); \ 472 | else \ 473 | (head)->cqh_last->field.cqe_next = (elm); \ 474 | (head)->cqh_last = (elm); \ 475 | } while (0) 476 | 477 | #define CIRCLEQ_REMOVE(head, elm, field) do { \ 478 | if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \ 479 | (head)->cqh_last = (elm)->field.cqe_prev; \ 480 | else \ 481 | (elm)->field.cqe_next->field.cqe_prev = \ 482 | (elm)->field.cqe_prev; \ 483 | if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \ 484 | (head)->cqh_first = (elm)->field.cqe_next; \ 485 | else \ 486 | (elm)->field.cqe_prev->field.cqe_next = \ 487 | (elm)->field.cqe_next; \ 488 | } while (0) 489 | 490 | #define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ 491 | if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \ 492 | CIRCLEQ_END(head)) \ 493 | (head).cqh_last = (elm2); \ 494 | else \ 495 | (elm2)->field.cqe_next->field.cqe_prev = (elm2); \ 496 | if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \ 497 | CIRCLEQ_END(head)) \ 498 | (head).cqh_first = (elm2); \ 499 | else \ 500 | (elm2)->field.cqe_prev->field.cqe_next = (elm2); \ 501 | } while (0) 502 | 503 | #endif /* !_SYS_QUEUE_H_ */ 504 | -------------------------------------------------------------------------------- /compat/sys/tree.h: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: tree.h,v 1.6 2002/06/11 22:09:52 provos Exp $ */ 2 | /* 3 | * Copyright 2002 Niels Provos 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef _SYS_TREE_H_ 28 | #define _SYS_TREE_H_ 29 | 30 | /* 31 | * This file defines data structures for different types of trees: 32 | * splay trees and red-black trees. 33 | * 34 | * A splay tree is a self-organizing data structure. Every operation 35 | * on the tree causes a splay to happen. The splay moves the requested 36 | * node to the root of the tree and partly rebalances it. 37 | * 38 | * This has the benefit that request locality causes faster lookups as 39 | * the requested nodes move to the top of the tree. On the other hand, 40 | * every lookup causes memory writes. 41 | * 42 | * The Balance Theorem bounds the total access time for m operations 43 | * and n inserts on an initially empty tree as O((m + n)lg n). The 44 | * amortized cost for a sequence of m accesses to a splay tree is O(lg n); 45 | * 46 | * A red-black tree is a binary search tree with the node color as an 47 | * extra attribute. It fulfills a set of conditions: 48 | * - every search path from the root to a leaf consists of the 49 | * same number of black nodes, 50 | * - each red node (except for the root) has a black parent, 51 | * - each leaf node is black. 52 | * 53 | * Every operation on a red-black tree is bounded as O(lg n). 54 | * The maximum height of a red-black tree is 2lg (n+1). 55 | */ 56 | 57 | #define SPLAY_HEAD(name, type) \ 58 | struct name { \ 59 | struct type *sph_root; /* root of the tree */ \ 60 | } 61 | 62 | #define SPLAY_INITIALIZER(root) \ 63 | { NULL } 64 | 65 | #define SPLAY_INIT(root) do { \ 66 | (root)->sph_root = NULL; \ 67 | } while (0) 68 | 69 | #define SPLAY_ENTRY(type) \ 70 | struct { \ 71 | struct type *spe_left; /* left element */ \ 72 | struct type *spe_right; /* right element */ \ 73 | } 74 | 75 | #define SPLAY_LEFT(elm, field) (elm)->field.spe_left 76 | #define SPLAY_RIGHT(elm, field) (elm)->field.spe_right 77 | #define SPLAY_ROOT(head) (head)->sph_root 78 | #define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL) 79 | 80 | /* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */ 81 | #define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \ 82 | SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ 83 | SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ 84 | (head)->sph_root = tmp; \ 85 | } while (0) 86 | 87 | #define SPLAY_ROTATE_LEFT(head, tmp, field) do { \ 88 | SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ 89 | SPLAY_LEFT(tmp, field) = (head)->sph_root; \ 90 | (head)->sph_root = tmp; \ 91 | } while (0) 92 | 93 | #define SPLAY_LINKLEFT(head, tmp, field) do { \ 94 | SPLAY_LEFT(tmp, field) = (head)->sph_root; \ 95 | tmp = (head)->sph_root; \ 96 | (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ 97 | } while (0) 98 | 99 | #define SPLAY_LINKRIGHT(head, tmp, field) do { \ 100 | SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ 101 | tmp = (head)->sph_root; \ 102 | (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ 103 | } while (0) 104 | 105 | #define SPLAY_ASSEMBLE(head, node, left, right, field) do { \ 106 | SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \ 107 | SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\ 108 | SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \ 109 | SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \ 110 | } while (0) 111 | 112 | /* Generates prototypes and inline functions */ 113 | 114 | #define SPLAY_PROTOTYPE(name, type, field, cmp) \ 115 | void name##_SPLAY(struct name *, struct type *); \ 116 | void name##_SPLAY_MINMAX(struct name *, int); \ 117 | struct type *name##_SPLAY_INSERT(struct name *, struct type *); \ 118 | struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \ 119 | \ 120 | /* Finds the node with the same key as elm */ \ 121 | static __inline struct type * \ 122 | name##_SPLAY_FIND(struct name *head, struct type *elm) \ 123 | { \ 124 | if (SPLAY_EMPTY(head)) \ 125 | return(NULL); \ 126 | name##_SPLAY(head, elm); \ 127 | if ((cmp)(elm, (head)->sph_root) == 0) \ 128 | return (head->sph_root); \ 129 | return (NULL); \ 130 | } \ 131 | \ 132 | static __inline struct type * \ 133 | name##_SPLAY_NEXT(struct name *head, struct type *elm) \ 134 | { \ 135 | name##_SPLAY(head, elm); \ 136 | if (SPLAY_RIGHT(elm, field) != NULL) { \ 137 | elm = SPLAY_RIGHT(elm, field); \ 138 | while (SPLAY_LEFT(elm, field) != NULL) { \ 139 | elm = SPLAY_LEFT(elm, field); \ 140 | } \ 141 | } else \ 142 | elm = NULL; \ 143 | return (elm); \ 144 | } \ 145 | \ 146 | static __inline struct type * \ 147 | name##_SPLAY_MIN_MAX(struct name *head, int val) \ 148 | { \ 149 | name##_SPLAY_MINMAX(head, val); \ 150 | return (SPLAY_ROOT(head)); \ 151 | } 152 | 153 | /* Main splay operation. 154 | * Moves node close to the key of elm to top 155 | */ 156 | #define SPLAY_GENERATE(name, type, field, cmp) \ 157 | struct type * \ 158 | name##_SPLAY_INSERT(struct name *head, struct type *elm) \ 159 | { \ 160 | if (SPLAY_EMPTY(head)) { \ 161 | SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \ 162 | } else { \ 163 | int __comp; \ 164 | name##_SPLAY(head, elm); \ 165 | __comp = (cmp)(elm, (head)->sph_root); \ 166 | if(__comp < 0) { \ 167 | SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\ 168 | SPLAY_RIGHT(elm, field) = (head)->sph_root; \ 169 | SPLAY_LEFT((head)->sph_root, field) = NULL; \ 170 | } else if (__comp > 0) { \ 171 | SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\ 172 | SPLAY_LEFT(elm, field) = (head)->sph_root; \ 173 | SPLAY_RIGHT((head)->sph_root, field) = NULL; \ 174 | } else \ 175 | return ((head)->sph_root); \ 176 | } \ 177 | (head)->sph_root = (elm); \ 178 | return (NULL); \ 179 | } \ 180 | \ 181 | struct type * \ 182 | name##_SPLAY_REMOVE(struct name *head, struct type *elm) \ 183 | { \ 184 | struct type *__tmp; \ 185 | if (SPLAY_EMPTY(head)) \ 186 | return (NULL); \ 187 | name##_SPLAY(head, elm); \ 188 | if ((cmp)(elm, (head)->sph_root) == 0) { \ 189 | if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ 190 | (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\ 191 | } else { \ 192 | __tmp = SPLAY_RIGHT((head)->sph_root, field); \ 193 | (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\ 194 | name##_SPLAY(head, elm); \ 195 | SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ 196 | } \ 197 | return (elm); \ 198 | } \ 199 | return (NULL); \ 200 | } \ 201 | \ 202 | void \ 203 | name##_SPLAY(struct name *head, struct type *elm) \ 204 | { \ 205 | struct type __node, *__left, *__right, *__tmp; \ 206 | int __comp; \ 207 | \ 208 | SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ 209 | __left = __right = &__node; \ 210 | \ 211 | while ((__comp = (cmp)(elm, (head)->sph_root))) { \ 212 | if (__comp < 0) { \ 213 | __tmp = SPLAY_LEFT((head)->sph_root, field); \ 214 | if (__tmp == NULL) \ 215 | break; \ 216 | if ((cmp)(elm, __tmp) < 0){ \ 217 | SPLAY_ROTATE_RIGHT(head, __tmp, field); \ 218 | if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ 219 | break; \ 220 | } \ 221 | SPLAY_LINKLEFT(head, __right, field); \ 222 | } else if (__comp > 0) { \ 223 | __tmp = SPLAY_RIGHT((head)->sph_root, field); \ 224 | if (__tmp == NULL) \ 225 | break; \ 226 | if ((cmp)(elm, __tmp) > 0){ \ 227 | SPLAY_ROTATE_LEFT(head, __tmp, field); \ 228 | if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ 229 | break; \ 230 | } \ 231 | SPLAY_LINKRIGHT(head, __left, field); \ 232 | } \ 233 | } \ 234 | SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ 235 | } \ 236 | \ 237 | /* Splay with either the minimum or the maximum element \ 238 | * Used to find minimum or maximum element in tree. \ 239 | */ \ 240 | void name##_SPLAY_MINMAX(struct name *head, int __comp) \ 241 | { \ 242 | struct type __node, *__left, *__right, *__tmp; \ 243 | \ 244 | SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ 245 | __left = __right = &__node; \ 246 | \ 247 | while (1) { \ 248 | if (__comp < 0) { \ 249 | __tmp = SPLAY_LEFT((head)->sph_root, field); \ 250 | if (__tmp == NULL) \ 251 | break; \ 252 | if (__comp < 0){ \ 253 | SPLAY_ROTATE_RIGHT(head, __tmp, field); \ 254 | if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ 255 | break; \ 256 | } \ 257 | SPLAY_LINKLEFT(head, __right, field); \ 258 | } else if (__comp > 0) { \ 259 | __tmp = SPLAY_RIGHT((head)->sph_root, field); \ 260 | if (__tmp == NULL) \ 261 | break; \ 262 | if (__comp > 0) { \ 263 | SPLAY_ROTATE_LEFT(head, __tmp, field); \ 264 | if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ 265 | break; \ 266 | } \ 267 | SPLAY_LINKRIGHT(head, __left, field); \ 268 | } \ 269 | } \ 270 | SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ 271 | } 272 | 273 | #define SPLAY_NEGINF -1 274 | #define SPLAY_INF 1 275 | 276 | #define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y) 277 | #define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y) 278 | #define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y) 279 | #define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y) 280 | #define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \ 281 | : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) 282 | #define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \ 283 | : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) 284 | 285 | #define SPLAY_FOREACH(x, name, head) \ 286 | for ((x) = SPLAY_MIN(name, head); \ 287 | (x) != NULL; \ 288 | (x) = SPLAY_NEXT(name, head, x)) 289 | 290 | /* Macros that define a red-back tree */ 291 | #define RB_HEAD(name, type) \ 292 | struct name { \ 293 | struct type *rbh_root; /* root of the tree */ \ 294 | } 295 | 296 | #define RB_INITIALIZER(root) \ 297 | { NULL } 298 | 299 | #define RB_INIT(root) do { \ 300 | (root)->rbh_root = NULL; \ 301 | } while (0) 302 | 303 | #define RB_BLACK 0 304 | #define RB_RED 1 305 | #define RB_ENTRY(type) \ 306 | struct { \ 307 | struct type *rbe_left; /* left element */ \ 308 | struct type *rbe_right; /* right element */ \ 309 | struct type *rbe_parent; /* parent element */ \ 310 | int rbe_color; /* node color */ \ 311 | } 312 | 313 | #define RB_LEFT(elm, field) (elm)->field.rbe_left 314 | #define RB_RIGHT(elm, field) (elm)->field.rbe_right 315 | #define RB_PARENT(elm, field) (elm)->field.rbe_parent 316 | #define RB_COLOR(elm, field) (elm)->field.rbe_color 317 | #define RB_ROOT(head) (head)->rbh_root 318 | #define RB_EMPTY(head) (RB_ROOT(head) == NULL) 319 | 320 | #define RB_SET(elm, parent, field) do { \ 321 | RB_PARENT(elm, field) = parent; \ 322 | RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \ 323 | RB_COLOR(elm, field) = RB_RED; \ 324 | } while (0) 325 | 326 | #define RB_SET_BLACKRED(black, red, field) do { \ 327 | RB_COLOR(black, field) = RB_BLACK; \ 328 | RB_COLOR(red, field) = RB_RED; \ 329 | } while (0) 330 | 331 | #ifndef RB_AUGMENT 332 | #define RB_AUGMENT(x) 333 | #endif 334 | 335 | #define RB_ROTATE_LEFT(head, elm, tmp, field) do { \ 336 | (tmp) = RB_RIGHT(elm, field); \ 337 | if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \ 338 | RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \ 339 | } \ 340 | RB_AUGMENT(elm); \ 341 | if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ 342 | if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ 343 | RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ 344 | else \ 345 | RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ 346 | RB_AUGMENT(RB_PARENT(elm, field)); \ 347 | } else \ 348 | (head)->rbh_root = (tmp); \ 349 | RB_LEFT(tmp, field) = (elm); \ 350 | RB_PARENT(elm, field) = (tmp); \ 351 | RB_AUGMENT(tmp); \ 352 | } while (0) 353 | 354 | #define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \ 355 | (tmp) = RB_LEFT(elm, field); \ 356 | if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \ 357 | RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \ 358 | } \ 359 | RB_AUGMENT(elm); \ 360 | if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ 361 | if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ 362 | RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ 363 | else \ 364 | RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ 365 | RB_AUGMENT(RB_PARENT(elm, field)); \ 366 | } else \ 367 | (head)->rbh_root = (tmp); \ 368 | RB_RIGHT(tmp, field) = (elm); \ 369 | RB_PARENT(elm, field) = (tmp); \ 370 | RB_AUGMENT(tmp); \ 371 | } while (0) 372 | 373 | /* Generates prototypes and inline functions */ 374 | #define RB_PROTOTYPE(name, type, field, cmp) \ 375 | void name##_RB_INSERT_COLOR(struct name *, struct type *); \ 376 | void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\ 377 | struct type *name##_RB_REMOVE(struct name *, struct type *); \ 378 | struct type *name##_RB_INSERT(struct name *, struct type *); \ 379 | struct type *name##_RB_FIND(struct name *, struct type *); \ 380 | struct type *name##_RB_NEXT(struct name *, struct type *); \ 381 | struct type *name##_RB_MINMAX(struct name *, int); \ 382 | \ 383 | 384 | /* Main rb operation. 385 | * Moves node close to the key of elm to top 386 | */ 387 | #define RB_GENERATE(name, type, field, cmp) \ 388 | void \ 389 | name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ 390 | { \ 391 | struct type *parent, *gparent, *tmp; \ 392 | while ((parent = RB_PARENT(elm, field)) && \ 393 | RB_COLOR(parent, field) == RB_RED) { \ 394 | gparent = RB_PARENT(parent, field); \ 395 | if (parent == RB_LEFT(gparent, field)) { \ 396 | tmp = RB_RIGHT(gparent, field); \ 397 | if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ 398 | RB_COLOR(tmp, field) = RB_BLACK; \ 399 | RB_SET_BLACKRED(parent, gparent, field);\ 400 | elm = gparent; \ 401 | continue; \ 402 | } \ 403 | if (RB_RIGHT(parent, field) == elm) { \ 404 | RB_ROTATE_LEFT(head, parent, tmp, field);\ 405 | tmp = parent; \ 406 | parent = elm; \ 407 | elm = tmp; \ 408 | } \ 409 | RB_SET_BLACKRED(parent, gparent, field); \ 410 | RB_ROTATE_RIGHT(head, gparent, tmp, field); \ 411 | } else { \ 412 | tmp = RB_LEFT(gparent, field); \ 413 | if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ 414 | RB_COLOR(tmp, field) = RB_BLACK; \ 415 | RB_SET_BLACKRED(parent, gparent, field);\ 416 | elm = gparent; \ 417 | continue; \ 418 | } \ 419 | if (RB_LEFT(parent, field) == elm) { \ 420 | RB_ROTATE_RIGHT(head, parent, tmp, field);\ 421 | tmp = parent; \ 422 | parent = elm; \ 423 | elm = tmp; \ 424 | } \ 425 | RB_SET_BLACKRED(parent, gparent, field); \ 426 | RB_ROTATE_LEFT(head, gparent, tmp, field); \ 427 | } \ 428 | } \ 429 | RB_COLOR(head->rbh_root, field) = RB_BLACK; \ 430 | } \ 431 | \ 432 | void \ 433 | name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \ 434 | { \ 435 | struct type *tmp; \ 436 | while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \ 437 | elm != RB_ROOT(head)) { \ 438 | if (RB_LEFT(parent, field) == elm) { \ 439 | tmp = RB_RIGHT(parent, field); \ 440 | if (RB_COLOR(tmp, field) == RB_RED) { \ 441 | RB_SET_BLACKRED(tmp, parent, field); \ 442 | RB_ROTATE_LEFT(head, parent, tmp, field);\ 443 | tmp = RB_RIGHT(parent, field); \ 444 | } \ 445 | if ((RB_LEFT(tmp, field) == NULL || \ 446 | RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ 447 | (RB_RIGHT(tmp, field) == NULL || \ 448 | RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ 449 | RB_COLOR(tmp, field) = RB_RED; \ 450 | elm = parent; \ 451 | parent = RB_PARENT(elm, field); \ 452 | } else { \ 453 | if (RB_RIGHT(tmp, field) == NULL || \ 454 | RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\ 455 | struct type *oleft; \ 456 | if ((oleft = RB_LEFT(tmp, field)))\ 457 | RB_COLOR(oleft, field) = RB_BLACK;\ 458 | RB_COLOR(tmp, field) = RB_RED; \ 459 | RB_ROTATE_RIGHT(head, tmp, oleft, field);\ 460 | tmp = RB_RIGHT(parent, field); \ 461 | } \ 462 | RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ 463 | RB_COLOR(parent, field) = RB_BLACK; \ 464 | if (RB_RIGHT(tmp, field)) \ 465 | RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\ 466 | RB_ROTATE_LEFT(head, parent, tmp, field);\ 467 | elm = RB_ROOT(head); \ 468 | break; \ 469 | } \ 470 | } else { \ 471 | tmp = RB_LEFT(parent, field); \ 472 | if (RB_COLOR(tmp, field) == RB_RED) { \ 473 | RB_SET_BLACKRED(tmp, parent, field); \ 474 | RB_ROTATE_RIGHT(head, parent, tmp, field);\ 475 | tmp = RB_LEFT(parent, field); \ 476 | } \ 477 | if ((RB_LEFT(tmp, field) == NULL || \ 478 | RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ 479 | (RB_RIGHT(tmp, field) == NULL || \ 480 | RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ 481 | RB_COLOR(tmp, field) = RB_RED; \ 482 | elm = parent; \ 483 | parent = RB_PARENT(elm, field); \ 484 | } else { \ 485 | if (RB_LEFT(tmp, field) == NULL || \ 486 | RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\ 487 | struct type *oright; \ 488 | if ((oright = RB_RIGHT(tmp, field)))\ 489 | RB_COLOR(oright, field) = RB_BLACK;\ 490 | RB_COLOR(tmp, field) = RB_RED; \ 491 | RB_ROTATE_LEFT(head, tmp, oright, field);\ 492 | tmp = RB_LEFT(parent, field); \ 493 | } \ 494 | RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ 495 | RB_COLOR(parent, field) = RB_BLACK; \ 496 | if (RB_LEFT(tmp, field)) \ 497 | RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\ 498 | RB_ROTATE_RIGHT(head, parent, tmp, field);\ 499 | elm = RB_ROOT(head); \ 500 | break; \ 501 | } \ 502 | } \ 503 | } \ 504 | if (elm) \ 505 | RB_COLOR(elm, field) = RB_BLACK; \ 506 | } \ 507 | \ 508 | struct type * \ 509 | name##_RB_REMOVE(struct name *head, struct type *elm) \ 510 | { \ 511 | struct type *child, *parent, *old = elm; \ 512 | int color; \ 513 | if (RB_LEFT(elm, field) == NULL) \ 514 | child = RB_RIGHT(elm, field); \ 515 | else if (RB_RIGHT(elm, field) == NULL) \ 516 | child = RB_LEFT(elm, field); \ 517 | else { \ 518 | struct type *left; \ 519 | elm = RB_RIGHT(elm, field); \ 520 | while ((left = RB_LEFT(elm, field))) \ 521 | elm = left; \ 522 | child = RB_RIGHT(elm, field); \ 523 | parent = RB_PARENT(elm, field); \ 524 | color = RB_COLOR(elm, field); \ 525 | if (child) \ 526 | RB_PARENT(child, field) = parent; \ 527 | if (parent) { \ 528 | if (RB_LEFT(parent, field) == elm) \ 529 | RB_LEFT(parent, field) = child; \ 530 | else \ 531 | RB_RIGHT(parent, field) = child; \ 532 | RB_AUGMENT(parent); \ 533 | } else \ 534 | RB_ROOT(head) = child; \ 535 | if (RB_PARENT(elm, field) == old) \ 536 | parent = elm; \ 537 | (elm)->field = (old)->field; \ 538 | if (RB_PARENT(old, field)) { \ 539 | if (RB_LEFT(RB_PARENT(old, field), field) == old)\ 540 | RB_LEFT(RB_PARENT(old, field), field) = elm;\ 541 | else \ 542 | RB_RIGHT(RB_PARENT(old, field), field) = elm;\ 543 | RB_AUGMENT(RB_PARENT(old, field)); \ 544 | } else \ 545 | RB_ROOT(head) = elm; \ 546 | RB_PARENT(RB_LEFT(old, field), field) = elm; \ 547 | if (RB_RIGHT(old, field)) \ 548 | RB_PARENT(RB_RIGHT(old, field), field) = elm; \ 549 | if (parent) { \ 550 | left = parent; \ 551 | do { \ 552 | RB_AUGMENT(left); \ 553 | } while ((left = RB_PARENT(left, field))); \ 554 | } \ 555 | goto color; \ 556 | } \ 557 | parent = RB_PARENT(elm, field); \ 558 | color = RB_COLOR(elm, field); \ 559 | if (child) \ 560 | RB_PARENT(child, field) = parent; \ 561 | if (parent) { \ 562 | if (RB_LEFT(parent, field) == elm) \ 563 | RB_LEFT(parent, field) = child; \ 564 | else \ 565 | RB_RIGHT(parent, field) = child; \ 566 | RB_AUGMENT(parent); \ 567 | } else \ 568 | RB_ROOT(head) = child; \ 569 | color: \ 570 | if (color == RB_BLACK) \ 571 | name##_RB_REMOVE_COLOR(head, parent, child); \ 572 | return (old); \ 573 | } \ 574 | \ 575 | /* Inserts a node into the RB tree */ \ 576 | struct type * \ 577 | name##_RB_INSERT(struct name *head, struct type *elm) \ 578 | { \ 579 | struct type *tmp; \ 580 | struct type *parent = NULL; \ 581 | int comp = 0; \ 582 | tmp = RB_ROOT(head); \ 583 | while (tmp) { \ 584 | parent = tmp; \ 585 | comp = (cmp)(elm, parent); \ 586 | if (comp < 0) \ 587 | tmp = RB_LEFT(tmp, field); \ 588 | else if (comp > 0) \ 589 | tmp = RB_RIGHT(tmp, field); \ 590 | else \ 591 | return (tmp); \ 592 | } \ 593 | RB_SET(elm, parent, field); \ 594 | if (parent != NULL) { \ 595 | if (comp < 0) \ 596 | RB_LEFT(parent, field) = elm; \ 597 | else \ 598 | RB_RIGHT(parent, field) = elm; \ 599 | RB_AUGMENT(parent); \ 600 | } else \ 601 | RB_ROOT(head) = elm; \ 602 | name##_RB_INSERT_COLOR(head, elm); \ 603 | return (NULL); \ 604 | } \ 605 | \ 606 | /* Finds the node with the same key as elm */ \ 607 | struct type * \ 608 | name##_RB_FIND(struct name *head, struct type *elm) \ 609 | { \ 610 | struct type *tmp = RB_ROOT(head); \ 611 | int comp; \ 612 | while (tmp) { \ 613 | comp = cmp(elm, tmp); \ 614 | if (comp < 0) \ 615 | tmp = RB_LEFT(tmp, field); \ 616 | else if (comp > 0) \ 617 | tmp = RB_RIGHT(tmp, field); \ 618 | else \ 619 | return (tmp); \ 620 | } \ 621 | return (NULL); \ 622 | } \ 623 | \ 624 | struct type * \ 625 | name##_RB_NEXT(struct name *head, struct type *elm) \ 626 | { \ 627 | if (RB_RIGHT(elm, field)) { \ 628 | elm = RB_RIGHT(elm, field); \ 629 | while (RB_LEFT(elm, field)) \ 630 | elm = RB_LEFT(elm, field); \ 631 | } else { \ 632 | if (RB_PARENT(elm, field) && \ 633 | (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ 634 | elm = RB_PARENT(elm, field); \ 635 | else { \ 636 | while (RB_PARENT(elm, field) && \ 637 | (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\ 638 | elm = RB_PARENT(elm, field); \ 639 | elm = RB_PARENT(elm, field); \ 640 | } \ 641 | } \ 642 | return (elm); \ 643 | } \ 644 | \ 645 | struct type * \ 646 | name##_RB_MINMAX(struct name *head, int val) \ 647 | { \ 648 | struct type *tmp = RB_ROOT(head); \ 649 | struct type *parent = NULL; \ 650 | while (tmp) { \ 651 | parent = tmp; \ 652 | if (val < 0) \ 653 | tmp = RB_LEFT(tmp, field); \ 654 | else \ 655 | tmp = RB_RIGHT(tmp, field); \ 656 | } \ 657 | return (parent); \ 658 | } 659 | 660 | #define RB_NEGINF -1 661 | #define RB_INF 1 662 | 663 | #define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) 664 | #define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) 665 | #define RB_FIND(name, x, y) name##_RB_FIND(x, y) 666 | #define RB_NEXT(name, x, y) name##_RB_NEXT(x, y) 667 | #define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) 668 | #define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) 669 | 670 | #define RB_FOREACH(x, name, head) \ 671 | for ((x) = RB_MIN(name, head); \ 672 | (x) != NULL; \ 673 | (x) = name##_RB_NEXT(head, x)) 674 | 675 | #endif /* _SYS_TREE_H_ */ 676 | --------------------------------------------------------------------------------