├── bootstrap ├── utils ├── Makefile.am ├── yrp2warts │ ├── Makefile │ ├── yarrpfile.hpp │ └── ipaddress.hpp ├── warts2yrp.py.1 ├── yrp2warts.py.1 ├── warts2yrp.py ├── yarrpfile.py └── yrp2warts.py ├── README.md ├── subnet.h ├── status.h ├── Makefile.am ├── subnet_list.h ├── CHANGES ├── mac.h ├── libcperm ├── cycle.h ├── feistel.h ├── prefix.h ├── ciphers │ ├── rc5.h │ ├── rc5.c │ ├── rc5-16.h │ ├── speck.h │ ├── rc5-16.c │ └── speck.c ├── cycle.c ├── feistel.c ├── prefix.c ├── cperm-internal.h ├── cperm.c └── cperm.h ├── LICENSE ├── yconfig.h ├── m4 ├── ax_check_compile_flag.m4 ├── ax_check_zlib.m4 └── ax_compare_version.m4 ├── trace.cpp ├── icmp.h ├── stats.h ├── subnet_list.cpp ├── status.cpp ├── random_list.h ├── trace.h ├── subnet.cpp ├── ttlhisto.h ├── random_list.cpp ├── util.cpp ├── configure.ac ├── listener.cpp ├── yarrp.h ├── entire.cpp ├── iplist.cpp ├── mac.cpp ├── listener6.cpp ├── patricia.h ├── trace6.cpp ├── yarrp.1 └── trace4.cpp /bootstrap: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Wrapper to build run GNU autoconf tool chain on yarrp project 3 | set -x 4 | autoreconf -fviW all 5 | -------------------------------------------------------------------------------- /utils/Makefile.am: -------------------------------------------------------------------------------- 1 | man_MANS = yrp2warts.py.1 warts2yrp.py.1 2 | 3 | EXTRA_DIST = \ 4 | $(man_MANS) \ 5 | yrp2warts.py \ 6 | warts2yrp.py \ 7 | yarrpfile.py 8 | -------------------------------------------------------------------------------- /utils/yrp2warts/Makefile: -------------------------------------------------------------------------------- 1 | CXX = c++ 2 | CFLAGS = -Os --std=gnu++11 -Wall 3 | LIBS = -lscamperfile 4 | DEPS = ipaddress.hpp yarrpfile.hpp 5 | OBJ = yrp2warts.o 6 | 7 | %.o: %.cpp $(DEPS) 8 | $(CXX) -c -o $@ $< $(CFLAGS) 9 | 10 | yrp2warts: $(OBJ) 11 | $(CXX) -o $@ $^ $(CFLAGS) $(LIBS) 12 | 13 | clean: 14 | rm -f yrp2warts yrp2warts.o -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Yarrp (Yelling at Random Routers Progressively) 2 | ========= 3 | 4 | Yarrp is a next-generation active network topology discovery technique and tool 5 | designed for rapid mapping at Internet scales. As with traditional traceroute, 6 | Yarrp discovers router interfaces and the links between them. However, Yarrp 7 | can probe at over 100Kpps and has been shown to discover >200K router 8 | interfaces in less than 5 minutes. Yarrp supports TCP, UDP-paris, and 9 | ICMP-paris probing over both IPv4 and IPv6. Yarrp is written in C++, runs on 10 | Linux and BSD systems, and is open-sourced with a BSD license. 11 | 12 | ## Build 13 | 14 | ```shell 15 | ./bootstrap 16 | ./configure 17 | make 18 | ``` 19 | 20 | ## Technical details 21 | 22 | * See https://www.cmand.org/yarrp 23 | -------------------------------------------------------------------------------- /subnet.h: -------------------------------------------------------------------------------- 1 | #ifndef SUBNET_H 2 | #define SUBNET_H 3 | 4 | #include 5 | #include 6 | 7 | class Subnet { 8 | public: 9 | Subnet(std::string s); 10 | ~Subnet(); 11 | 12 | uint32_t first(); 13 | uint32_t last(); 14 | uint32_t count(); 15 | 16 | private: 17 | uint32_t start; 18 | uint32_t end; 19 | uint32_t offset; 20 | uint8_t smask; 21 | }; 22 | 23 | class Subnet6 { 24 | public: 25 | Subnet6(std::string s, uint8_t granularity); 26 | ~Subnet6(); 27 | uint64_t count() { 28 | return cnt; 29 | } 30 | struct in6_addr *first(); 31 | 32 | private: 33 | struct in6_addr start; 34 | struct in6_addr end; 35 | struct in6_addr offset; 36 | uint8_t smask; 37 | uint64_t cnt; 38 | }; 39 | 40 | #endif /* SUBNET_H */ 41 | -------------------------------------------------------------------------------- /status.h: -------------------------------------------------------------------------------- 1 | #ifndef _STATUS_H_ 2 | #define _STATUS_H_ 3 | 4 | #ifndef UINT8_MAX 5 | #define UINT8_MAX (255) 6 | #endif 7 | 8 | #include 9 | 10 | class Status { 11 | public: 12 | Status() : probes(0), returns(0), lastSent(0), lastReply(0), 13 | highTTL(1), lowTTL(UINT8_MAX) 14 | { 15 | missingTTL.clear(); 16 | }; 17 | void print(); 18 | void reset(); 19 | void probed(uint8_t ttl, uint32_t elapsed); 20 | void result(uint8_t ttl, uint32_t elapsed); 21 | uint8_t getTTL() { return highTTL; } 22 | bool shouldProbe(); 23 | 24 | private: 25 | void printMissingTTL(); 26 | uint16_t probes; 27 | uint16_t returns; 28 | uint32_t lastSent; 29 | uint32_t lastReply; 30 | uint8_t highTTL; 31 | uint8_t lowTTL; 32 | std::unordered_set missingTTL; 33 | }; 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /utils/warts2yrp.py.1: -------------------------------------------------------------------------------- 1 | .\" 2 | .\" yarrp.1 3 | .\" 4 | .\" Author: Robert Beverly 5 | .\" 6 | .\" Copyright (c) 2016 Robert Beverly 7 | .\" All rights reserved 8 | .\" 9 | .\" 10 | .Dd May 4, 2018 11 | .Dt WARTS2YRP.PY 1 12 | .Os 13 | .Sh NAME 14 | .Nm warts2yrp.py 15 | .Nd convert binary warts to yarrp format output file 16 | .Sh SYNOPSIS 17 | .Nm 18 | .Bk -words 19 | .Op Fl h 20 | .Op Fl i Ar input 21 | .Op Fl o Ar output 22 | .Sh DESCRIPTION 23 | .Nm 24 | converts standard binary warts format (the 25 | native format for scamper) to yarrp formatted output. Requires sc_warts.py from 26 | https://www.github.com/cmand/scamper. 27 | .Pp 28 | The options are as follows: 29 | .Bl -tag -width Ds 30 | .It Fl h 31 | prints a list of command line options and a synopsis of each. 32 | .It Fl i Ar input 33 | input Yarrp file 34 | .It Fl o Ar output 35 | output warts file 36 | .El 37 | .Sh EXAMPLES 38 | The command: 39 | .Pp 40 | .in +.3i 41 | warts2yrp.py -i test.warts -o test.yrp 42 | .in -.3i 43 | .Pp 44 | will convert test.warts, a binary warts traceroute file, to a new 45 | yarrp formatted test.yrp file. 46 | .Pp 47 | .in -.5i 48 | .Sh SEE ALSO 49 | .Xr yarrp 1 50 | .Sh AUTHORS 51 | .Nm 52 | is written by Robert Beverly . 53 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = utils 2 | 3 | bin_PROGRAMS = yarrp 4 | 5 | yarrp_SOURCES = \ 6 | icmp.cpp \ 7 | iplist.cpp \ 8 | listener.cpp \ 9 | listener6.cpp \ 10 | mac.cpp \ 11 | net.cpp \ 12 | patricia.cpp \ 13 | random_list.cpp \ 14 | status.cpp \ 15 | subnet.cpp \ 16 | subnet_list.cpp \ 17 | trace.cpp \ 18 | trace4.cpp \ 19 | trace6.cpp \ 20 | util.cpp \ 21 | yarrp.cpp \ 22 | yconfig.cpp \ 23 | libcperm/cperm.c \ 24 | libcperm/prefix.c \ 25 | libcperm/cycle.c \ 26 | libcperm/ciphers/rc5.c \ 27 | libcperm/ciphers/rc5-16.c \ 28 | libcperm/ciphers/speck.c 29 | 30 | include_HEADERS = \ 31 | icmp.h \ 32 | mac.h \ 33 | patricia.h \ 34 | random_list.h \ 35 | stats.h \ 36 | status.h \ 37 | subnet.h \ 38 | subnet_list.h \ 39 | trace.h \ 40 | ttlhisto.h \ 41 | yarrp.h \ 42 | yconfig.h \ 43 | libcperm/cperm.h \ 44 | libcperm/cperm-internal.h \ 45 | libcperm/cycle.h \ 46 | libcperm/feistel.h \ 47 | libcperm/prefix.h \ 48 | libcperm/ciphers/rc5-16.h \ 49 | libcperm/ciphers/rc5.h \ 50 | libcperm/ciphers/speck.h 51 | 52 | man_MANS = \ 53 | yarrp.1 54 | 55 | EXTRA_DIST = \ 56 | $(man_MANS) \ 57 | LICENSE \ 58 | CHANGES 59 | 60 | yarrp.1.pdf: yarrp.1 61 | man -t ./yarrp.1 | ps2pdf - > yarrp.1.pdf 62 | -------------------------------------------------------------------------------- /subnet_list.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | Program: $Id: $ 3 | Date: $Date: $ 4 | Description: subnet list 5 | ****************************************************************************/ 6 | 7 | #ifndef SUBNET_LIST_H 8 | #define SUBNET_LIST_H 9 | #include 10 | #include 11 | #include 12 | 13 | #include "subnet.h" 14 | 15 | using namespace std; 16 | 17 | class SubnetList { 18 | public: 19 | SubnetList(uint8_t maxttl, uint8_t gran); 20 | virtual ~SubnetList(); 21 | virtual void add_subnet(string s, bool ipv6); 22 | virtual uint32_t next_address(struct in_addr *in, uint8_t *ttl); 23 | virtual uint32_t next_address(struct in6_addr *in, uint8_t *ttl); 24 | uint32_t count(); 25 | 26 | protected: 27 | list subnets; 28 | list subnets6; 29 | uint32_t addr_count; 30 | uint8_t maxttl; 31 | uint8_t granularity; 32 | uint32_t ttlmask_bits; 33 | uint32_t ttlmask; 34 | 35 | uint16_t getHost(uint8_t *addr); 36 | 37 | private: 38 | list::iterator current_subnet; 39 | list::iterator current_subnet6; 40 | uint32_t current_twentyfour; 41 | uint32_t current_48; 42 | uint8_t current_ttl; 43 | }; 44 | 45 | #endif /* SUBNET_LIST_H */ 46 | -------------------------------------------------------------------------------- /CHANGES: -------------------------------------------------------------------------------- 1 | yarrp-0.8 2 | --------- 3 | * Fix memory leaks 4 | * IPv6 subnet probing 5 | * IPv6 blocklist support 6 | * Better BGP table support 7 | * Misc bug fixes 8 | 9 | yarrp-0.7 10 | --------- 11 | * Add IPv6 EH support 12 | * Add ICMP MPLS extension support 13 | * FreeBSD verison >=11 fixes 14 | 15 | yarrp-0.6 16 | --------- 17 | * Add blocklist support 18 | * Option to accept targets from stdin 19 | * Option to export results to stdout 20 | * Structured yrp output format 21 | * Instance locking 22 | * Fixed rate control 23 | * Add minimum TTL option 24 | * Fast C++ yrp2warts processor 25 | * Bundle libcperm 26 | * Misc stability fixes 27 | 28 | yarrp-0.5 29 | --------- 30 | * Add fill mode 31 | * Support IPv6 on BSD 32 | * Support multiple simultaneous instances 33 | * Support ICMP echo reply probes 34 | 35 | yarrp-0.4 36 | --------- 37 | * Multiple IPv6 fixes 38 | * Support IPv6 BGP tables 39 | * Support IPv4 ICMP probing 40 | * Add probe-to-end TTL enhancement 41 | * Microsecond timestamp support 42 | * Record permutation seed in output 43 | * Decoupled probing/receiving support 44 | * Beta Internet6-wide probing support 45 | * Updated yrp2warts utilities 46 | 47 | yarrp-0.3 48 | --------- 49 | * IPv6 support 50 | * Require libcperm 51 | 52 | yarrp-0.2 53 | --------- 54 | * Support UDP probing 55 | * Configurable transport destination port 56 | 57 | yarrp-0.1 58 | --------- 59 | * Initial public release 60 | -------------------------------------------------------------------------------- /mac.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | Program: $Id: net.cpp 14 2014-12-30 02:33:44Z laalt $ 3 | Date: $Date: 2014-12-29 18:33:44 -0800 (Mon, 29 Dec 2014) $ 4 | Description: networking routines 5 | ****************************************************************************/ 6 | #include "yarrp.h" 7 | 8 | #ifdef _LINUX 9 | #include 10 | #include 11 | #endif 12 | #include 13 | #include 14 | 15 | #define BUFSIZE 8192 16 | #define IPV6SIZE 16 17 | #ifndef ETH_ALEN 18 | #define ETH_ALEN 6 19 | #endif 20 | 21 | struct gw_info { 22 | uint32_t ip; 23 | char ip6[IPV6SIZE]; 24 | char mac[ETH_ALEN]; 25 | char mac6[ETH_ALEN]; 26 | }; 27 | 28 | class LLResolv { 29 | public: 30 | LLResolv() {}; 31 | 32 | char *mac2str(char *mac); 33 | void mine(const char *interface); 34 | void gateway(); 35 | int print_gw(); 36 | void print_self(); 37 | void setSrcMAC(uint8_t **mac); 38 | void setDstMAC(uint8_t **mac); 39 | 40 | private: 41 | struct gw_info gw; 42 | struct ifreq ifr; /* Linux netdevice(7) */ 43 | int sock; 44 | 45 | int send_req(char *buf, size_t nlseq, size_t req_type); 46 | int read_res(char *buf, size_t nlseq); 47 | void parse_route(struct nlmsghdr *nlmsg); 48 | void parse_neigh(struct nlmsghdr *nlmsg); 49 | }; 50 | -------------------------------------------------------------------------------- /libcperm/cycle.h: -------------------------------------------------------------------------------- 1 | /* ------------------------------------------------------------------------ 2 | libcperm - A library for creating random permutations. 3 | Copyright (c) 2014, Lance Alt 4 | 5 | This file is part of libcperm. 6 | 7 | This library is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Lesser General Public License as published 9 | by the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License 18 | along with this library. If not, see . 19 | ------------------------------------------------------------------------ 20 | */ 21 | 22 | 23 | #ifndef CYCLE_H 24 | #define CYCLE_H 25 | 26 | #include 27 | #include "cperm.h" 28 | 29 | struct cycle_data_t { 30 | uint64_t next; 31 | uint64_t count; 32 | }; 33 | 34 | int perm_cycle_create(struct cperm_t* perm); 35 | int perm_cycle_get(struct cperm_t* perm, uint64_t pt, uint64_t* ct); 36 | int perm_cycle_next(struct cperm_t* perm, uint64_t* ct); 37 | int perm_cycle_destroy(struct cperm_t* perm); 38 | 39 | #endif /* CYCLE_H */ 40 | -------------------------------------------------------------------------------- /utils/yrp2warts.py.1: -------------------------------------------------------------------------------- 1 | .\" 2 | .\" yrp2warts.py.1 3 | .\" 4 | .\" Author: Robert Beverly 5 | .\" 6 | .\" Copyright (c) 2016-2019 Robert Beverly 7 | .\" All rights reserved 8 | .\" 9 | .\" 10 | .Dd November 15, 2019 11 | .Dt YRP2WARTS.PY 1 12 | .Os 13 | .Sh NAME 14 | .Nm yrp2warts.py 15 | .Nd convert Yarrp format output to binary warts 16 | .Sh SYNOPSIS 17 | .Nm 18 | .Bk -words 19 | .Op Fl h 20 | .Op Fl i Ar input 21 | .Op Fl o Ar output 22 | .Op Fl s Ar subnet 23 | .Sh DESCRIPTION 24 | .Nm 25 | converts Yarrp output files to the standard binary warts format (the 26 | native format for scamper). Requires sc_warts_writer.py from 27 | https://www.github.com/cmand/scamper. 28 | .Pp 29 | The options are as follows: 30 | .Bl -tag -width Ds 31 | .It Fl h 32 | prints a list of command line options and a synopsis of each. 33 | .It Fl i Ar input 34 | input Yarrp file 35 | .It Fl o Ar output 36 | output warts file 37 | .It Fl s Ar subnet 38 | optional filter to restrict conversion to a single subnet 39 | .El 40 | .Sh EXAMPLES 41 | The command: 42 | .Pp 43 | .in +.3i 44 | yrp2warts.py -i test.yrp -o test.warts 45 | .in -.3i 46 | .Pp 47 | will convert test.yrp, containing output from a Yarrp run, to a new 48 | warts formatted test.warts file. 49 | .Pp 50 | .in -.5i 51 | .Sh SEE ALSO 52 | .Xr yarrp 1 53 | .Sh AUTHORS 54 | .Nm 55 | is written by Robert Beverly . 56 | Justin Rohrer contributed a pure C++ yrp2warts implementation. 57 | -------------------------------------------------------------------------------- /libcperm/feistel.h: -------------------------------------------------------------------------------- 1 | /* ------------------------------------------------------------------------ 2 | libcperm - A library for creating random permutations. 3 | Copyright (c) 2014, Lance Alt 4 | 5 | This file is part of libcperm. 6 | 7 | This library is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Lesser General Public License as published 9 | by the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License 18 | along with this library. If not, see . 19 | ------------------------------------------------------------------------ 20 | */ 21 | 22 | 23 | #ifndef FEISTEL_H 24 | #define FEISTEL_H 25 | 26 | #include 27 | #include "cperm.h" 28 | 29 | struct feistel_data_t { 30 | uint32_t next; 31 | uint32_t count; 32 | }; 33 | 34 | int perm_feistel_create(struct perm_t* perm); 35 | int perm_feistel_get(struct perm_t* perm, uint32_t pt, uint32_t* ct); 36 | int perm_feistel_next(struct perm_t* perm, uint32_t* ct); 37 | int perm_feistel_destroy(struct perm_t* perm); 38 | 39 | #endif /* FEISTEL_H */ 40 | -------------------------------------------------------------------------------- /libcperm/prefix.h: -------------------------------------------------------------------------------- 1 | /* ------------------------------------------------------------------------ 2 | libcperm - A library for creating random permutations. 3 | Copyright (c) 2014, Lance Alt 4 | 5 | This file is part of libcperm. 6 | 7 | This library is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Lesser General Public License as published 9 | by the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License 18 | along with this library. If not, see . 19 | ------------------------------------------------------------------------ 20 | */ 21 | 22 | 23 | #ifndef PREFIX_H 24 | #define PREFIX_H 25 | 26 | #include 27 | #include "cperm.h" 28 | 29 | struct prefix_element { 30 | uint64_t pt; 31 | uint64_t ct; 32 | }; 33 | 34 | struct prefix_data_t { 35 | struct prefix_element* vector; 36 | uint64_t next; 37 | }; 38 | 39 | int perm_prefix_create(struct cperm_t* perm); 40 | int perm_prefix_get(struct cperm_t* perm, uint64_t pt, uint64_t* ct); 41 | int perm_prefix_next(struct cperm_t* perm, uint64_t* ct); 42 | int perm_prefix_destroy(struct cperm_t* perm); 43 | 44 | #endif /* PREFIX_H */ 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016-2024 Robert Beverly 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. The names of the authors and copyright holders may not be used to 14 | endorse or promote products derived from this software without 15 | specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 20 | NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 22 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /yconfig.h: -------------------------------------------------------------------------------- 1 | typedef std::pair val_t; 2 | typedef std::map params_t; 3 | 4 | class YarrpConfig { 5 | public: 6 | YarrpConfig() : rate(10), random_scan(true), ttl_neighborhood(0), 7 | testing(false), entire(false), output(NULL), 8 | bgpfile(NULL), inlist(NULL), blocklist(NULL), 9 | count(0), minttl(1), maxttl(16), seed(0), 10 | dstport(80), 11 | ipv6(false), int_name(NULL), dstmac(NULL), srcmac(NULL), 12 | coarse(false), fillmode(32), poisson(0), 13 | probesrc(NULL), probe(true), receive(true), instance(0), v6_eh(255), out(NULL) {}; 14 | 15 | void parse_opts(int argc, char **argv); 16 | void usage(char *prog); 17 | void set(std::string, std::string, bool); 18 | void dump() { if (output) dump(out); } 19 | unsigned int rate; 20 | bool random_scan; 21 | uint8_t ttl_neighborhood; 22 | bool testing; 23 | bool entire; /* speed as sole emphasis, to scan entire Internet */ 24 | char *output; 25 | char *bgpfile; 26 | char *inlist; 27 | char *blocklist; 28 | uint32_t count; 29 | uint8_t minttl; 30 | uint8_t maxttl; 31 | uint32_t seed; 32 | uint16_t dstport; 33 | bool ipv6; 34 | char *int_name; 35 | uint8_t *dstmac; 36 | uint8_t *srcmac; 37 | int type; 38 | bool coarse; 39 | int fillmode; 40 | int poisson; 41 | char *probesrc; 42 | bool probe; 43 | bool receive; 44 | uint8_t instance; 45 | uint8_t v6_eh; 46 | uint8_t granularity; 47 | FILE *out; /* output file stream */ 48 | params_t params; 49 | 50 | private: 51 | void dump(FILE *fd); 52 | }; 53 | -------------------------------------------------------------------------------- /libcperm/ciphers/rc5.h: -------------------------------------------------------------------------------- 1 | /* ------------------------------------------------------------------------ 2 | libcperm - A library for creating random permutations. 3 | Copyright (c) 2014, Lance Alt 4 | 5 | This file is part of libcperm. 6 | 7 | This library is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Lesser General Public License as published 9 | by the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License 18 | along with this library. If not, see . 19 | ------------------------------------------------------------------------ 20 | */ 21 | 22 | 23 | #ifndef RC5_H 24 | #define RC5_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "../cperm.h" 32 | #include "rc5-16.h" 33 | 34 | struct rc5_data { 35 | struct rc5_key key; 36 | uint32_t* blocks; 37 | uint32_t index; 38 | }; 39 | 40 | int perm_rc5_create(struct cperm_t* pt); 41 | int perm_rc5_destroy(struct cperm_t* pt); 42 | int perm_rc5_enc(struct cperm_t* perm, uint64_t pt, uint64_t* ct); 43 | int perm_rc5_dec(struct cperm_t* perm, uint64_t ct, uint64_t* pt); 44 | 45 | #endif /* RC5_H */ 46 | -------------------------------------------------------------------------------- /libcperm/ciphers/rc5.c: -------------------------------------------------------------------------------- 1 | /* ------------------------------------------------------------------------ 2 | libcperm - A library for creating random permutations. 3 | Copyright (c) 2014, Lance Alt 4 | 5 | This file is part of libcperm. 6 | 7 | This library is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Lesser General Public License as published 9 | by the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License 18 | along with this library. If not, see . 19 | ------------------------------------------------------------------------ 20 | */ 21 | 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "../cperm.h" 29 | #include "../cperm-internal.h" 30 | #include "rc5-16.h" 31 | 32 | struct rc5_data { 33 | struct rc5_key key; 34 | uint32_t* blocks; 35 | uint32_t index; 36 | }; 37 | 38 | int perm_rc5_create(struct cperm_t* pt) { 39 | struct rc5_data* d; 40 | 41 | if(pt->key_len != RC5_KEYLEN) { 42 | return PERM_ERROR_BAD_KEY_LENGTH; 43 | } 44 | 45 | d = malloc(sizeof(*d)); 46 | memcpy(&d->key, pt->key, pt->key_len); 47 | 48 | pt->cipher_data = d; 49 | rc5_setup(pt->cipher_data); 50 | 51 | return 0; 52 | } 53 | 54 | int perm_rc5_destroy(struct cperm_t* pt) { 55 | free(pt->cipher_data); 56 | return 0; 57 | } 58 | 59 | int perm_rc5_enc(struct cperm_t* perm, uint32_t pt, uint32_t* ct) { 60 | struct rc5_data* d = perm->cipher_data; 61 | rc5_ecb_encrypt(&d->key, &pt, ct); 62 | return 0; 63 | } 64 | 65 | int perm_rc5_dec(struct cperm_t* perm, uint32_t ct, uint32_t* pt) { 66 | struct rc5_data* d = perm->cipher_data; 67 | rc5_ecb_decrypt(&d->key, &ct, pt); 68 | return 0; 69 | } 70 | 71 | -------------------------------------------------------------------------------- /libcperm/cycle.c: -------------------------------------------------------------------------------- 1 | /* ------------------------------------------------------------------------ 2 | libcperm - A library for creating random permutations. 3 | Copyright (c) 2014, Lance Alt 4 | 5 | This file is part of libcperm. 6 | 7 | This library is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Lesser General Public License as published 9 | by the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License 18 | along with this library. If not, see . 19 | ------------------------------------------------------------------------ 20 | */ 21 | 22 | 23 | #include 24 | #include 25 | 26 | #include "cperm.h" 27 | #include "cperm-internal.h" 28 | #include "cycle.h" 29 | 30 | int perm_cycle_create(struct cperm_t* perm) { 31 | struct cycle_data_t* cycle_data = calloc(1,sizeof(*cycle_data)); 32 | if(!cycle_data) { 33 | cperm_errno = PERM_ERROR_NOMEM; 34 | return PERM_ERROR_NOMEM; 35 | } 36 | 37 | cycle_data->next = 0; 38 | cycle_data->count = 0; 39 | perm->mode_data = cycle_data; 40 | 41 | return 0; 42 | } 43 | 44 | int perm_cycle_get(struct cperm_t* perm, uint64_t pt, uint64_t* ct) { 45 | cperm_errno = PERM_ERROR_OP_NOT_SUPP; 46 | return PERM_ERROR_OP_NOT_SUPP; 47 | } 48 | 49 | int perm_cycle_next(struct cperm_t* perm, uint64_t* ct) { 50 | struct cycle_data_t* cycle_data = perm->mode_data; 51 | 52 | if(cycle_data->count >= perm->range) { 53 | cperm_errno = PERM_END; 54 | return PERM_END; 55 | } 56 | 57 | do { 58 | perm->cipher->enc(perm, cycle_data->next, ct); 59 | cycle_data->next++; 60 | }while(*ct >= perm->range); 61 | 62 | cycle_data->count++; 63 | 64 | return 0; 65 | } 66 | 67 | int perm_cycle_destroy(struct cperm_t* perm) { 68 | free(perm->mode_data); 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /m4/ax_check_compile_flag.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check whether the given FLAG works with the current language's compiler 12 | # or gives an error. (Warnings, however, are ignored) 13 | # 14 | # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on 15 | # success/failure. 16 | # 17 | # If EXTRA-FLAGS is defined, it is added to the current language's default 18 | # flags (e.g. CFLAGS) when the check is done. The check is thus made with 19 | # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to 20 | # force the compiler to issue an error when a bad flag is given. 21 | # 22 | # INPUT gives an alternative input source to AC_COMPILE_IFELSE. 23 | # 24 | # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this 25 | # macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. 26 | # 27 | # LICENSE 28 | # 29 | # Copyright (c) 2008 Guido U. Draheim 30 | # Copyright (c) 2011 Maarten Bosmans 31 | # 32 | # Copying and distribution of this file, with or without modification, are 33 | # permitted in any medium without royalty provided the copyright notice 34 | # and this notice are preserved. This file is offered as-is, without any 35 | # warranty. 36 | 37 | #serial 6 38 | 39 | AC_DEFUN([AX_CHECK_COMPILE_FLAG], 40 | [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF 41 | AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl 42 | AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ 43 | ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS 44 | _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" 45 | AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], 46 | [AS_VAR_SET(CACHEVAR,[yes])], 47 | [AS_VAR_SET(CACHEVAR,[no])]) 48 | _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) 49 | AS_VAR_IF(CACHEVAR,yes, 50 | [m4_default([$2], :)], 51 | [m4_default([$3], :)]) 52 | AS_VAR_POPDEF([CACHEVAR])dnl 53 | ])dnl AX_CHECK_COMPILE_FLAGS 54 | -------------------------------------------------------------------------------- /trace.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | Program: $Id: trace.cpp 39 2015-12-30 20:28:36Z rbeverly $ 3 | Date: $Date: 2015-12-30 12:28:36 -0800 (Wed, 30 Dec 2015) $ 4 | Description: traceroute class 5 | ****************************************************************************/ 6 | #include "yarrp.h" 7 | 8 | Traceroute::Traceroute(YarrpConfig *_config, Stats *_stats) : config(_config), stats(_stats), tree(NULL), recv_thread() 9 | { 10 | dstport = config->dstport; 11 | if (config->ttl_neighborhood) 12 | initHisto(config->ttl_neighborhood); 13 | gettimeofday(&start, NULL); 14 | debug(HIGH, ">> Traceroute engine started: " << start.tv_sec); 15 | // RFC2822 timestring 16 | struct tm *p = localtime(&(start.tv_sec)); 17 | char s[1000]; 18 | strftime(s, 1000, "%a, %d %b %Y %T %z", p); 19 | config->set("Start", s, true); 20 | pthread_mutex_init(&recv_lock, NULL); 21 | } 22 | 23 | Traceroute::~Traceroute() { 24 | gettimeofday(&start, NULL); 25 | debug(HIGH, ">> Traceroute engine stopped: " << start.tv_sec); 26 | fflush(NULL); 27 | pthread_cancel(recv_thread); 28 | if (config->out) 29 | fclose(config->out); 30 | } 31 | 32 | void 33 | Traceroute::initHisto(uint8_t ttl) { 34 | cout << ">> Init TTL histogram for neighborhood: " << int(ttl) << endl; 35 | for (int i = 0; i <= ttl; i++) { 36 | TTLHisto *t = NULL; 37 | if (config->ipv6) 38 | t = new TTLHisto6(); 39 | else 40 | t = new TTLHisto4(); 41 | ttlhisto.push_back(t); 42 | } 43 | } 44 | 45 | void 46 | Traceroute::dumpHisto() { 47 | if (ttlhisto.size() == 0) 48 | return; 49 | cout << ">> Dumping TTL Histogram:" << endl; 50 | for (int i = 1; i < ttlhisto.size(); i++) { 51 | TTLHisto *t = ttlhisto[i]; 52 | cout << "\tTTL: " << i << " "; 53 | t->dump(); 54 | } 55 | } 56 | 57 | uint32_t 58 | Traceroute::elapsed() { 59 | gettimeofday(&now, NULL); 60 | if (config->coarse) 61 | return tsdiff(&now, &start); 62 | return tsdiffus(&now, &start); 63 | } 64 | 65 | void 66 | Traceroute::lock() { 67 | pthread_mutex_lock(&recv_lock); 68 | } 69 | 70 | void 71 | Traceroute::unlock() { 72 | pthread_mutex_unlock(&recv_lock); 73 | } 74 | -------------------------------------------------------------------------------- /libcperm/ciphers/rc5-16.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: rc5-16.h 3 | * Author: zvrba 4 | * Created: 2008-04-08 5 | * 6 | * =========================================================================== 7 | * COPYRIGHT (c) 2008 Zeljko Vrba 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a 10 | * copy of this software and associated documentation files (the "Software"), 11 | * to deal in the Software without restriction, including without limitation 12 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | * and/or sell copies of the Software, and to permit persons to whom the 14 | * Software is furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in 17 | * all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | * DEALINGS IN THE SOFTWARE. 26 | * =========================================================================== 27 | */ 28 | /** 29 | * @file 30 | * Interfaces for RC5-16 encryption. 31 | */ 32 | 33 | #ifndef RC5_16_H__ 34 | #define RC5_16_H__ 35 | 36 | #define RC5_BLOCKSZ 4 /* (bytes) */ 37 | #define RC5_KEYLEN 16 /* (bytes) */ 38 | #define RC5_ROUNDS 12 /* # of rounds */ 39 | 40 | typedef unsigned short RC5_WORD; 41 | 42 | struct rc5_key { 43 | unsigned char key[RC5_KEYLEN]; 44 | RC5_WORD S[2*(RC5_ROUNDS+1)]; 45 | }; 46 | 47 | /** 48 | * Expand the key. On entry, the the ks->key field must be initialized with 49 | * the desired key. 50 | */ 51 | void rc5_setup(struct rc5_key *ks); 52 | 53 | /** Encrypt a single block. It is allowed that src == dst. */ 54 | void rc5_ecb_encrypt(const struct rc5_key *ks, void *src, void *dst); 55 | 56 | /** Decrypt a single block. It is allowed that src == dst. */ 57 | void rc5_ecb_decrypt(const struct rc5_key *ks, void *src, void *dst); 58 | 59 | #endif /* RC5_16_H__ */ 60 | -------------------------------------------------------------------------------- /icmp.h: -------------------------------------------------------------------------------- 1 | typedef struct mpls_label { 2 | uint32_t label:20; 3 | uint8_t exp:4; 4 | uint8_t ttl; 5 | struct mpls_label *next; 6 | } mpls_label_t; 7 | #define MAX_MPLS_STACK_HEIGHT 4 8 | 9 | typedef struct icmp_extension { 10 | uint8_t ver:4; 11 | uint16_t reserved:12; 12 | uint16_t cksum; 13 | uint16_t len; 14 | uint8_t c_num; 15 | uint8_t c_type; 16 | } icmp_extension_t; 17 | 18 | class ICMP { 19 | public: 20 | ICMP(); 21 | ~ICMP(); 22 | virtual void print() {}; 23 | virtual void write(FILE **, uint32_t) {}; 24 | virtual uint32_t getSrc() { return 0; }; 25 | virtual struct in6_addr *getSrc6() { return NULL; }; 26 | virtual uint32_t quoteDst() { return 0; }; 27 | virtual struct in6_addr quoteDst6() { struct in6_addr a; return a; }; 28 | void printterse(char *); 29 | uint8_t quoteTTL() { return ttl; } 30 | uint32_t getRTT() { return rtt; } 31 | uint32_t getTTL() { return ttl; } 32 | uint16_t getSport() { return sport; } 33 | uint16_t getDport() { return dport; } 34 | uint8_t getInstance() { return instance; } 35 | void print(char *, char *, int); 36 | void write(FILE **, uint32_t, char *, char *); 37 | char *getMPLS(); 38 | bool is_yarrp; 39 | 40 | protected: 41 | uint32_t rtt; 42 | uint8_t ttl; 43 | uint8_t instance; 44 | uint8_t type; 45 | uint8_t code; 46 | uint8_t length; 47 | uint8_t quote_p; 48 | uint16_t sport; 49 | uint16_t dport; 50 | uint16_t ipid; 51 | uint16_t probesize; 52 | uint16_t replysize; 53 | uint8_t replyttl; 54 | uint8_t replytos; 55 | struct timeval tv; 56 | bool coarse; 57 | mpls_label_t *mpls_stack; 58 | }; 59 | 60 | class ICMP4 : public ICMP { 61 | public: 62 | ICMP4(struct ip *, struct icmp *, uint32_t elapsed, bool _coarse); 63 | uint32_t quoteDst(); 64 | uint32_t getSrc() { return ip_src.s_addr; } 65 | void print(); 66 | void write(FILE **, uint32_t); 67 | 68 | private: 69 | struct ip *quote; 70 | struct in_addr ip_src; 71 | }; 72 | 73 | class ICMP6 : public ICMP { 74 | public: 75 | ICMP6(struct ip6_hdr *, struct icmp6_hdr *, uint32_t elapsed, bool _coarse); 76 | struct in6_addr *getSrc6() { return &ip_src; } 77 | struct in6_addr quoteDst6(); 78 | void print(); 79 | void write(FILE **, uint32_t); 80 | 81 | private: 82 | struct ip6_hdr *quote; 83 | struct in6_addr ip_src; 84 | struct in6_addr *yarrp_target; 85 | }; 86 | 87 | -------------------------------------------------------------------------------- /stats.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class Stats { 4 | public: 5 | Stats() : count(0), to_probe(0), nbr_skipped(0), bgp_skipped(0), 6 | ttl_outside(0), bgp_outside(0), adr_outside(0), baddst(0), 7 | fills(0) { 8 | gettimeofday(&start, NULL); 9 | }; 10 | void terse() { 11 | terse(stderr); 12 | } 13 | void terse(FILE *out) { 14 | gettimeofday(&end, NULL); 15 | float t = (float) tsdiff(&end, &start) / 1000.0; 16 | fprintf(out, "# %" PRId64 "/%" PRId64 " (%2.1f%%), NBskip: %" PRId64 "/%" PRId64 " TBAout: %" PRId64 "/%" PRId64 "/%" PRId64 " Bad: %" PRId64 " Fill: %" PRId64, 17 | count, to_probe, (float) count*100.0/to_probe, 18 | nbr_skipped, bgp_skipped, ttl_outside, 19 | bgp_outside, adr_outside, baddst, fills); 20 | fprintf(out, " in: %2.1fs (%2.1f pps)\n", 21 | t, (float) count / t); 22 | }; 23 | void dump(FILE *out) { 24 | gettimeofday(&end, NULL); 25 | float t = (float) tsdiff(&end, &start) / 1000.0; 26 | // RFC2822 timestring 27 | struct tm *p = localtime(&(end.tv_sec)); 28 | char s[1000]; 29 | strftime(s, 1000, "%a, %d %b %Y %T %z", p); 30 | fprintf(out, "# End: %s\n", s); 31 | fprintf(out, "# Bad_Resp: %" PRId64 "\n", baddst); 32 | fprintf(out, "# Fills: %" PRId64 "\n", fills); 33 | fprintf(out, "# Outside_TTL: %" PRId64 "\n", ttl_outside); 34 | fprintf(out, "# Outside_BGP: %" PRId64 "\n", bgp_outside); 35 | fprintf(out, "# Outside_Addr: %" PRId64 "\n", adr_outside); 36 | fprintf(out, "# Skipped_Nbr: %" PRId64 "\n", nbr_skipped); 37 | fprintf(out, "# Skipped_BGP: %" PRId64 "\n", bgp_skipped); 38 | fprintf(out, "# Pkts: %" PRId64 "\n", count); 39 | fprintf(out, "# Elapsed: %2.2fs\n", t); 40 | fprintf(out, "# PPS: %2.2f\n", (float) count / t); 41 | fprintf(out, "#\n"); 42 | }; 43 | 44 | uint64_t count; // number of probes sent 45 | uint64_t to_probe; 46 | uint64_t nbr_skipped; // b/c already in learned neighborhood 47 | uint64_t bgp_skipped; // b/c BGP learned 48 | uint64_t ttl_outside; // b/c outside range of TTLs we want 49 | uint64_t bgp_outside; // b/c not in BGP table 50 | uint64_t adr_outside; // b/c address outside range we want 51 | uint64_t baddst; // b/c checksum invalid on destination in reponse 52 | uint64_t fills; // extra tail probes past maxttl 53 | 54 | struct timeval start; 55 | struct timeval end; 56 | }; 57 | -------------------------------------------------------------------------------- /libcperm/feistel.c: -------------------------------------------------------------------------------- 1 | /* ------------------------------------------------------------------------ 2 | libcperm - A library for creating random permutations. 3 | Copyright (c) 2014, Lance Alt 4 | 5 | This file is part of libcperm. 6 | 7 | This library is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Lesser General Public License as published 9 | by the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License 18 | along with this library. If not, see . 19 | ------------------------------------------------------------------------ 20 | */ 21 | 22 | 23 | #include 24 | #include 25 | 26 | #include "cperm.h" 27 | #include "cperm-internal.h" 28 | #include "feistel.h" 29 | #include "ciphers/rc5.h" 30 | 31 | int perm_feistel_create(struct perm_t* perm) { 32 | struct feistel_data_t* feistel_data = malloc(sizeof(*feistel_data)); 33 | if(!feistel_data) { 34 | perm_errno = PERM_ERROR_NOMEM; 35 | return -1; 36 | } 37 | 38 | feistel_data->next = 0; 39 | feistel_data->count = 0; 40 | perm->mode_data = feistel_data; 41 | 42 | return 0; 43 | } 44 | 45 | int perm_feistel_get(struct perm_t* perm, uint32_t pt, uint32_t* ct) { 46 | perm_errno = PERM_ERROR_RANGE; 47 | return -1; 48 | } 49 | 50 | int perm_feistel_next(struct perm_t* perm, uint32_t* ct) { 51 | struct feistel_data_t* feistel_data = perm->mode_data; 52 | 53 | c = fe(r, a, b); 54 | 55 | if(feistel_data->count >= perm->range) { 56 | perm_errno = PERM_END; 57 | return PERM_END; 58 | } 59 | 60 | do { 61 | perm_rc5_enc(perm, feistel_data->next, ct); 62 | feistel_data->next++; 63 | }while(*ct >= perm->range); 64 | 65 | feistel_data->count++; 66 | 67 | return 0; 68 | } 69 | 70 | int perm_feistel_destroy(struct perm_t* perm) { 71 | free(perm->mode_data); 72 | return 0; 73 | } 74 | 75 | uint32_t fe(int r, int a, int b, int m) { 76 | int L = m % a; 77 | int R = m / a; 78 | 79 | for(int j = 0; j < r; j++) { 80 | if(j % 2 == 1) { 81 | tmp = L + F(R) % a; 82 | } else { 83 | tmp = L + F(R) % b; 84 | } 85 | L = R; 86 | R = tmp; 87 | } 88 | if(r % 2 == 1) { 89 | return a * L + R; 90 | } else { 91 | return a * R + L; 92 | } 93 | } 94 | 95 | uint32_t F(uint32_t pt) { 96 | uint32_t ct; 97 | perm->cipher->enc(perm, &v, &ct); 98 | return ct; 99 | } 100 | -------------------------------------------------------------------------------- /subnet_list.cpp: -------------------------------------------------------------------------------- 1 | #include "yarrp.h" 2 | #include "subnet_list.h" 3 | 4 | SubnetList::SubnetList(uint8_t _maxttl, uint8_t _gran) : maxttl(_maxttl), granularity(_gran) { 5 | addr_count = 0; 6 | current_twentyfour = 0; 7 | current_48 = 0; 8 | current_ttl = 0; 9 | ttlmask_bits = intlog(maxttl); 10 | ttlmask = (1 << ttlmask_bits) - 1; 11 | }; 12 | 13 | SubnetList::~SubnetList() { 14 | }; 15 | 16 | void 17 | SubnetList::add_subnet(string s, bool ipv6) { 18 | if (ipv6) { 19 | Subnet6 subnet = Subnet6(s, granularity); 20 | subnets6.push_back(subnet); 21 | current_subnet6 = subnets6.begin(); 22 | addr_count += subnet.count() * maxttl; 23 | } else { 24 | Subnet subnet = Subnet(s); 25 | subnets.push_back(subnet); 26 | current_subnet = subnets.begin(); 27 | addr_count += subnet.count() * maxttl; 28 | } 29 | } 30 | 31 | uint32_t 32 | SubnetList::next_address(struct in6_addr *in, uint8_t * ttl) { 33 | if (current_subnet6 == subnets6.end()) { 34 | return 0; 35 | } 36 | *ttl = current_ttl; 37 | 38 | // don't muck w/ the iterator; copy 39 | memcpy(in, current_subnet6->first(), sizeof(struct in6_addr)); 40 | 41 | /* since we're dividing in /48s: 42 | - increment second word's high 16 bits by current_48 43 | - only increment first word (32bits) if we overflow current_48 16 bits 44 | */ 45 | int word0 = current_48 / 65536; 46 | int word1 = current_48 % 65536; 47 | 48 | (*in).s6_addr32[0] += htonl(word0); 49 | (*in).s6_addr32[1] += htonl(word1<<16); 50 | (*in).s6_addr32[3] += htonl(getHost(0)); 51 | /* 52 | char output[INET6_ADDRSTRLEN]; 53 | inet_ntop(AF_INET6, in, output, INET6_ADDRSTRLEN); 54 | cout << "Start: " << output << endl; 55 | */ 56 | if (++current_ttl > maxttl) { 57 | current_ttl = 0; 58 | current_48 += 1; 59 | } 60 | if (current_48 >= (*current_subnet6).count()) { 61 | current_48 = 0; 62 | current_subnet6++; 63 | } 64 | return 1; 65 | } 66 | 67 | uint32_t 68 | SubnetList::next_address(struct in_addr *in, uint8_t * ttl) { 69 | if (current_subnet == subnets.end()) { 70 | return 0; 71 | } 72 | in->s_addr = htonl((*current_subnet).first() + (current_twentyfour << 8) + getHost(0)); 73 | *ttl = current_ttl; 74 | if (++current_ttl > maxttl) { 75 | current_ttl = 0; 76 | current_twentyfour += 1; 77 | } 78 | if (current_twentyfour >= (*current_subnet).count()) { 79 | current_twentyfour = 0; 80 | current_subnet++; 81 | } 82 | return 1; 83 | } 84 | 85 | uint32_t 86 | SubnetList::count() { 87 | return addr_count; 88 | } 89 | 90 | uint16_t 91 | SubnetList::getHost(uint8_t * addr) { 92 | return 1; 93 | } 94 | -------------------------------------------------------------------------------- /status.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | Program: $Id: status.cpp 32 2015-01-10 23:05:29Z rbeverly $ 3 | Date: $Date: 2015-01-07 15:59:34 -0800 (Wed, 07 Jan 2015) $ 4 | Description: yarrp status. A status object exists per-BGP prefix as the 5 | node data in the patricia trie. Keep per-prefix status 6 | information as we proceed through the probing. 7 | ****************************************************************************/ 8 | #include "yarrp.h" 9 | 10 | void 11 | Status::print() { 12 | int32_t delta = lastReply - lastSent; 13 | std::cout << ">> Prefix status:" << std::endl; 14 | std::cout << "\tProbes: " << probes << " Returns: " << returns << std::endl; 15 | std::cout << "\tLast Probed: " << lastSent << " Last reply: " << lastReply; 16 | std::cout << " delta: " << delta << std::endl; 17 | std::cout << "\tTTL high: " << int (highTTL) << " TTL low: " << int (lowTTL) << std::endl; 18 | printMissingTTL(); 19 | } 20 | 21 | void 22 | Status::printMissingTTL() { 23 | std::cout << "\tMissing TTL: "; 24 | for (std::unordered_set < uint8_t >::iterator iter = missingTTL.begin(); 25 | iter != missingTTL.end(); 26 | iter++) { 27 | std::cout << int (*iter) << " "; 28 | } 29 | std::cout << std::endl; 30 | } 31 | 32 | void 33 | Status::reset() { 34 | probes = 0; 35 | returns = 0; 36 | lastReply = 0; 37 | highTTL = 0; 38 | lowTTL = UINT8_MAX; 39 | missingTTL.clear(); 40 | } 41 | 42 | /* 43 | * After a prefix is probed, update its status to indicate such 44 | */ 45 | void 46 | Status::probed(uint8_t ttl, uint32_t elapsed) { 47 | lastSent = elapsed; 48 | missingTTL.insert(int (ttl)); 49 | probes++; 50 | } 51 | 52 | /* 53 | * After a result comes back in response to a particular prefix being probed, 54 | * update the prefix's status 55 | */ 56 | void 57 | Status::result(uint8_t ttl, uint32_t elapsed) { 58 | returns++; 59 | lastReply = elapsed; 60 | if (ttl > highTTL) 61 | highTTL = ttl; 62 | if (ttl < lowTTL) 63 | lowTTL = ttl; 64 | missingTTL.erase(int (ttl)); 65 | } 66 | 67 | /* 68 | * Decision function as to whether the prefix should be probed. Implements a 69 | * basic stochastic grandient descent 70 | */ 71 | bool 72 | Status::shouldProbe() { 73 | uint8_t bob = highTTL + 1; 74 | if (missingTTL.find(bob) == missingTTL.end()) { 75 | //std::cout << __func__ << " got response for last TTL" << std: :endl; 76 | return true; 77 | } 78 | /* If no reply after sending, delta is positive */ 79 | int32_t delta = (lastSent - lastReply); 80 | double P = decayprob(delta, 60 * 1000); 81 | double r = zrand(); 82 | std::cout << ">> shouldProbe Delta: " << delta << " P: " << P << " r: " << r << std::endl; 83 | if (r > P) { 84 | highTTL++; 85 | lastReply = lastSent; 86 | } 87 | return true; 88 | } 89 | -------------------------------------------------------------------------------- /libcperm/prefix.c: -------------------------------------------------------------------------------- 1 | /* ------------------------------------------------------------------------ 2 | libcperm - A library for creating random permutations. 3 | Copyright (c) 2014, Lance Alt 4 | 5 | This file is part of libcperm. 6 | 7 | This library is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Lesser General Public License as published 9 | by the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License 18 | along with this library. If not, see . 19 | ------------------------------------------------------------------------ 20 | */ 21 | 22 | 23 | #include 24 | #include 25 | 26 | #include "cperm.h" 27 | #include "cperm-internal.h" 28 | #include "prefix.h" 29 | 30 | static int prefix_element_sort(const void* a, const void* b) { 31 | const struct prefix_element* ea = a; 32 | const struct prefix_element* eb = b; 33 | 34 | if(ea->ct < eb->ct) return -1; 35 | else return 1; 36 | } 37 | 38 | int perm_prefix_create(struct cperm_t* perm) { 39 | struct prefix_data_t* prefix_data = calloc(1,sizeof(*prefix_data)); 40 | if(!prefix_data) { 41 | cperm_errno = PERM_ERROR_NOMEM; 42 | return PERM_ERROR_NOMEM; 43 | } 44 | 45 | struct prefix_element* vect = calloc(perm->range, sizeof(struct prefix_element)); 46 | if(!vect) { 47 | free(prefix_data); 48 | cperm_errno = PERM_ERROR_NOMEM; 49 | return PERM_ERROR_NOMEM; 50 | } 51 | 52 | for(uint64_t i = 0; i < perm->range; i++) { 53 | perm->cipher->enc(perm, i, &vect[i].ct); 54 | vect[i].pt = i; 55 | } 56 | 57 | qsort(vect, perm->range, sizeof(struct prefix_element), prefix_element_sort); 58 | 59 | prefix_data->vector = vect; 60 | prefix_data->next = 0; 61 | perm->mode_data = prefix_data; 62 | 63 | return 0; 64 | } 65 | 66 | int perm_prefix_get(struct cperm_t* perm, uint64_t pt, uint64_t* ct) { 67 | struct prefix_data_t* prefix_data = perm->mode_data; 68 | 69 | if(pt < perm->range) { 70 | *ct = prefix_data->vector[pt].pt; 71 | return 0; 72 | } 73 | 74 | cperm_errno = PERM_ERROR_RANGE; 75 | return PERM_ERROR_RANGE; 76 | } 77 | 78 | int perm_prefix_next(struct cperm_t* perm, uint64_t* ct) { 79 | struct prefix_data_t* prefix_data = perm->mode_data; 80 | 81 | if(prefix_data->next < perm->range) { 82 | *ct = prefix_data->vector[prefix_data->next++].pt; 83 | return 0; 84 | } 85 | 86 | cperm_errno = PERM_END; 87 | return PERM_END; 88 | } 89 | 90 | int perm_prefix_destroy(struct cperm_t* perm) { 91 | struct prefix_data_t* prefix_data = perm->mode_data; 92 | free(prefix_data->vector); 93 | free(prefix_data); 94 | return 0; 95 | } 96 | -------------------------------------------------------------------------------- /random_list.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | Program: $Id: $ 3 | Date: $Date: $ 4 | Description: random subnet list 5 | ****************************************************************************/ 6 | 7 | #ifndef RANDOM_LIST_H 8 | #define RANDOM_LIST_H 9 | 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "libcperm/cperm.h" 16 | 17 | #include "subnet_list.h" 18 | 19 | using namespace std; 20 | 21 | class RandomSubnetList : public SubnetList { 22 | public: 23 | RandomSubnetList(uint8_t _maxttl, uint8_t _gran); 24 | ~RandomSubnetList(); 25 | 26 | uint32_t rand(uint32_t min, uint32_t max); 27 | void seed(); 28 | virtual uint32_t next_address(struct in_addr *in, uint8_t *ttl); 29 | virtual uint32_t next_address(struct in6_addr *in, uint8_t *ttl); 30 | 31 | private: 32 | uint16_t getHost(uint8_t *addr); 33 | uint64_t rndIID(uint32_t *addr); 34 | uint8_t key[32]; 35 | bool seeded; 36 | cperm_t* perm; 37 | }; 38 | 39 | class IPList { 40 | public: 41 | IPList(uint8_t _maxttl, bool _rand, bool _entire); 42 | virtual ~IPList() {}; 43 | virtual uint32_t next_address(struct in_addr *in, uint8_t * ttl) = 0; 44 | virtual uint32_t next_address(struct in6_addr *in, uint8_t * ttl) = 0; 45 | virtual void seed() = 0; 46 | void read(char *in); 47 | virtual void read(std::istream& in) = 0; 48 | uint32_t count() { return permsize; } 49 | void setkey(int seed); 50 | 51 | protected: 52 | uint8_t log2(uint8_t x); 53 | uint8_t key[KEYLEN]; 54 | cperm_t* perm; 55 | uint64_t permsize; 56 | uint8_t maxttl; 57 | uint8_t ttlbits; 58 | uint32_t ttlmask; 59 | uint32_t ttlprefix; 60 | bool rand; 61 | bool entire; 62 | bool seeded; 63 | }; 64 | 65 | class IPList4 : public IPList { 66 | public: 67 | IPList4(uint8_t _maxttl, bool _rand, bool _entire) : IPList(_maxttl, _rand, _entire) {}; 68 | virtual ~IPList4(); 69 | uint32_t next_address(struct in_addr *in, uint8_t * ttl); 70 | uint32_t next_address_seq(struct in_addr *in, uint8_t * ttl); 71 | uint32_t next_address_rand(struct in_addr *in, uint8_t * ttl); 72 | uint32_t next_address_entire(struct in_addr *in, uint8_t * ttl); 73 | uint32_t next_address(struct in6_addr *in, uint8_t * ttl) { return 0; }; 74 | void read(std::istream& in); 75 | void seed(); 76 | 77 | private: 78 | std::vector targets; 79 | }; 80 | 81 | class IPList6 : public IPList { 82 | public: 83 | IPList6(uint8_t _maxttl, bool _rand, bool _entire) : IPList(_maxttl, _rand, _entire) {}; 84 | virtual ~IPList6(); 85 | uint32_t next_address(struct in6_addr *in, uint8_t * ttl); 86 | uint32_t next_address_seq(struct in6_addr *in, uint8_t * ttl); 87 | uint32_t next_address_rand(struct in6_addr *in, uint8_t * ttl); 88 | uint32_t next_address_entire(struct in6_addr *in, uint8_t * ttl); 89 | uint32_t next_address(struct in_addr *in, uint8_t * ttl) { return 0; }; 90 | void read(std::istream& in); 91 | void seed(); 92 | 93 | private: 94 | std::vector targets; 95 | }; 96 | 97 | #endif /* RANDOM_LIST_H */ 98 | -------------------------------------------------------------------------------- /libcperm/cperm-internal.h: -------------------------------------------------------------------------------- 1 | /* ------------------------------------------------------------------------ 2 | libcperm - A library for creating random permutations. 3 | Copyright (c) 2014, Lance Alt 4 | 5 | This file is part of libcperm. 6 | 7 | This library is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Lesser General Public License as published 9 | by the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License 18 | along with this library. If not, see . 19 | ------------------------------------------------------------------------ 20 | */ 21 | 22 | 23 | #ifndef PERM_INTERNAL_H 24 | #define PERM_INTERNAL_H 25 | /* Internal libperm header. Not to be included by programs using the library. */ 26 | #include 27 | #include "cperm.h" 28 | 29 | /* Permutation mode and cipher function definitions */ 30 | typedef int (*ModeCreateFunc)(struct cperm_t*); 31 | typedef int (*ModeNextFunc)(struct cperm_t*, uint64_t*); 32 | typedef int (*ModeGetFunc)(struct cperm_t*, uint64_t, uint64_t*); 33 | typedef int (*ModeDestroyFunc)(struct cperm_t*); 34 | 35 | typedef int (*CipherCreateFunc)(struct cperm_t*); 36 | typedef int (*CipherEncFunc)(struct cperm_t*, uint64_t, uint64_t*); 37 | typedef int (*CipherDecFunc)(struct cperm_t*, uint64_t, uint64_t*); 38 | typedef int (*CipherDestroyFunc)(struct cperm_t*); 39 | 40 | /* libperm supports pluggable permutation modes and ciphers. They are defined by using 41 | ModeFuncs and CipherFuncs structures. */ 42 | struct ModeFuncs { 43 | PermMode mode; 44 | ModeCreateFunc create; 45 | ModeNextFunc next; 46 | ModeGetFunc get; 47 | ModeDestroyFunc destroy; 48 | }; 49 | 50 | struct CipherFuncs { 51 | PermCipher algo; 52 | CipherCreateFunc create; 53 | CipherEncFunc enc; 54 | CipherDecFunc dec; 55 | CipherDestroyFunc destroy; 56 | }; 57 | 58 | /* struct perm_t 59 | Main data structure containing the state for a single permutation. This structure is opaque to the 60 | user. It is returned from the perm_create() function and is passed as the first parameter to all the 61 | functions that operate on the permutation. Freed by calling the perm_destroy() function. 62 | */ 63 | struct cperm_t { 64 | uint8_t* key; // Buffer containing the cipher key 65 | uint16_t key_len; // Length of the key 66 | uint64_t range; // Range (size) of the permutation 67 | uint64_t position; // Position of the permutation (i.e. how many values have been read) 68 | void* mode_data; // Data specific to the permutation mode used 69 | void* cipher_data; // Data specific to the cipher used 70 | 71 | struct ModeFuncs* mode; // Function pointers for the selected permutation mode 72 | struct CipherFuncs* cipher; // Function pointers for the selected cipher 73 | }; 74 | 75 | #endif /* PERM_INTERNAL_H */ 76 | -------------------------------------------------------------------------------- /trace.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | Program: $Id: $ 3 | Date: $Date: $ 4 | Description: trace structures 5 | ****************************************************************************/ 6 | 7 | /* Payload for IPv6 Yarrp probes */ 8 | struct ypayload { 9 | uint32_t id; /* "yrp6" = 0x79 72 70 36 */ 10 | struct in6_addr target; /* v6 target address, to detect spoofed responses */ 11 | uint8_t instance; /* instance */ 12 | uint8_t ttl; /* sent TTL */ 13 | uint16_t fudge; /* make chksum constant */ 14 | uint32_t diff; /* elapsed time */ 15 | }; 16 | 17 | class Traceroute { 18 | public: 19 | Traceroute(YarrpConfig *config, Stats *stats); 20 | virtual ~Traceroute(); 21 | void addTree(Patricia *_tree) { 22 | tree = _tree; 23 | } 24 | void addStats(Stats *_stats) { 25 | stats = _stats; 26 | } 27 | void initHisto(uint8_t); 28 | void dumpHisto(); 29 | uint32_t elapsed(); 30 | void lock(); 31 | void unlock(); 32 | virtual void probe(uint32_t, int) {}; 33 | virtual void probe(struct sockaddr_in *, int) {}; 34 | virtual void probePrint(struct in_addr *, int) {}; 35 | virtual void probe(struct in6_addr, int) {}; 36 | virtual void probePrint(struct in6_addr, int) {}; 37 | 38 | public: 39 | Patricia *tree; 40 | Stats *stats; 41 | YarrpConfig *config; 42 | vector ttlhisto; 43 | 44 | protected: 45 | int sndsock; /* raw socket descriptor */ 46 | int payloadlen; 47 | int packlen; 48 | pthread_t recv_thread; 49 | pthread_mutex_t recv_lock; 50 | uint16_t dstport; 51 | struct timeval start; 52 | struct timeval now; 53 | }; 54 | 55 | class Traceroute4 : public Traceroute { 56 | public: 57 | Traceroute4(YarrpConfig *config, Stats *stats); 58 | virtual ~Traceroute4(); 59 | struct sockaddr_in *getSource() { return &source; } 60 | void probe(const char *, int); 61 | void probe(uint32_t, int); 62 | void probe(struct sockaddr_in *, int); 63 | void probePrint(struct in_addr *, int); 64 | 65 | private: 66 | void probeUDP(struct sockaddr_in *, int); 67 | void probeTCP(struct sockaddr_in *, int); 68 | void probeICMP(struct sockaddr_in *, int); 69 | struct ip *outip; 70 | struct sockaddr_in source; 71 | char addrstr[INET_ADDRSTRLEN]; 72 | }; 73 | 74 | class Traceroute6 : public Traceroute { 75 | public: 76 | Traceroute6(YarrpConfig *config, Stats *stats); 77 | virtual ~Traceroute6(); 78 | struct sockaddr_in6 *getSource() { return &source6; } 79 | void probe(struct in6_addr, int); 80 | void probePrint(struct in6_addr, int); 81 | void probe(void *, struct in6_addr, int); 82 | 83 | private: 84 | void make_transport(int); 85 | void make_frag_eh(uint8_t); 86 | void make_hbh_eh(uint8_t); 87 | struct ip6_hdr *outip; 88 | uint8_t *frame; 89 | int pcount; 90 | uint8_t tc = 0; /* traffic class which we always set to 0 */ 91 | uint32_t flow = 0; /* flow label which we always set to 0 */ 92 | struct sockaddr_in6 source6; 93 | struct ypayload *payload; 94 | char addrstr[INET6_ADDRSTRLEN]; 95 | }; 96 | -------------------------------------------------------------------------------- /libcperm/ciphers/speck.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, Moritz Bitsch 3 | 4 | Permission to use, copy, modify, and/or distribute this software for any 5 | purpose with or without fee is hereby granted, provided that the above 6 | copyright notice and this permission notice appear in all copies. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | #ifndef SPECK_H 17 | #define SPECK_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #include 24 | #include 25 | #include 26 | #include "../cperm.h" 27 | #include "../cperm-internal.h" 28 | 29 | #define MASK24 0xFFFFFF 30 | #define MASK48 0xFFFFFFFFFFFF 31 | 32 | /* 33 | * define speck type to use (one of SPECK_32_64, SPECK_64_128, SPECK_128_256) 34 | */ 35 | #define SPECK_32_64 36 | 37 | #ifdef SPECK_32_64 38 | #define SPECK_TYPE uint16_t 39 | #define SPECK_ROUNDS 22 40 | #define SPECK_KEY_LEN 4 41 | #endif 42 | 43 | #ifdef SPECK_48_72 44 | #define SPECK_TYPE uint32_t 45 | #define SPECK_ROUNDS 22 46 | #define SPECK_KEY_LEN 3 47 | #define WORDSIZE 24 48 | #endif 49 | 50 | #ifdef SPECK_48_96 51 | #define SPECK_TYPE uint32_t 52 | #define SPECK_ROUNDS 23 53 | #define SPECK_KEY_LEN 4 54 | #define WORDSIZE 24 55 | #endif 56 | 57 | #ifdef SPECK_64_128 58 | #define SPECK_TYPE uint32_t 59 | #define SPECK_ROUNDS 27 60 | #define SPECK_KEY_LEN 4 61 | #endif 62 | 63 | #ifdef SPECK_96_96 64 | #define SPECK_TYPE uint64_t 65 | #define SPECK_ROUNDS 28 66 | #define SPECK_KEY_LEN 2 67 | #define WORDSIZE 48 68 | #endif 69 | 70 | #ifdef SPECK_96_144 71 | #define SPECK_TYPE uint64_t 72 | #define SPECK_ROUNDS 29 73 | #define SPECK_KEY_LEN 3 74 | #define WORDSIZE 48 75 | #endif 76 | 77 | #ifdef SPECK_128_256 78 | #define SPECK_TYPE uint64_t 79 | #define SPECK_ROUNDS 34 80 | #define SPECK_KEY_LEN 4 81 | #endif 82 | 83 | void speck_expand(SPECK_TYPE const K[static SPECK_KEY_LEN], SPECK_TYPE S[static SPECK_ROUNDS]); 84 | void speck_encrypt(SPECK_TYPE const pt[static 2], SPECK_TYPE ct[static 2], SPECK_TYPE const K[static SPECK_ROUNDS]); 85 | void speck_decrypt(SPECK_TYPE const ct[static 2], SPECK_TYPE pt[static 2], SPECK_TYPE const K[static SPECK_ROUNDS]); 86 | 87 | void speck_encrypt_combined(SPECK_TYPE const pt[static 2], SPECK_TYPE ct[static 2], SPECK_TYPE const K[static SPECK_KEY_LEN]); 88 | void speck_decrypt_combined(SPECK_TYPE const ct[static 2], SPECK_TYPE pt[static 2], SPECK_TYPE const K[static SPECK_KEY_LEN]); 89 | 90 | int perm_speck_create(struct cperm_t *pt); 91 | int perm_speck_destroy(struct cperm_t* pt); 92 | int perm_speck_enc(struct cperm_t* perm, uint64_t pt, uint64_t* ct); 93 | int perm_speck_dec(struct cperm_t* perm, uint64_t ct, uint64_t* pt); 94 | 95 | #ifdef __cplusplus 96 | } 97 | #endif 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /utils/warts2yrp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Copyright (c) 2018, Robert Beverly 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 are met: 8 | # * Redistributions of source code must retain the above copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # * Neither the name of the nor the 14 | # names of its contributors may be used to endorse or promote products 15 | # derived from this software without specific prior written permission. 16 | # 17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AN 18 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | # DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 21 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | # 28 | # Program: $Id: warts2yrp.py $ 29 | # Author: Robert Beverly 30 | # Description: Convert binary warts to yarrp output 31 | # 32 | import argparse 33 | import sys 34 | import time 35 | from datetime import datetime 36 | try: 37 | from sc_warts import WartsReader 38 | except: 39 | print("Requires sc_warts.py from https://github.com/cmand/scamper/") 40 | sys.exit(-1) 41 | 42 | 43 | def main(): 44 | parser = argparse.ArgumentParser() 45 | parser.add_argument("-i", "--input", required=True, help="input warts file") 46 | parser.add_argument("-o", "--output", required=True, help="output yrp file") 47 | args = parser.parse_args() 48 | 49 | w = WartsReader(args.input, verbose=False) 50 | fd = open(args.output, 'w') 51 | 52 | print(">>", datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S')) 53 | # target, sec, usec, type, code, ttl, hop, rtt, ipid, psize, rsize, rttl, rtos, count 54 | count = 0 55 | while True: 56 | (flags, hops) = w.next() 57 | if flags == False: break 58 | #print flags 59 | target = flags['dstaddr'] 60 | n = flags['probesent'] 61 | for hop in hops: 62 | count+=1 63 | (sec, usec) = (0,0) 64 | (typ, code) = (hop['icmp-type'], hop['icmp-code']) 65 | router = hop['addr'] 66 | (ttl, rttl) = (hop['probettl'], hop['replyttl']) 67 | (ipid, rtt) = (hop['ipid'], hop['rtt']) 68 | (psize, rsize) = (hop['probesize'], hop['replysize']) 69 | rtos = hop['tos'] 70 | yrpline = [target, sec, usec, typ, code, ttl, router, rtt, ipid, psize, rsize, rttl, rtos, count] 71 | line = " ".join([str(x) for x in yrpline]) 72 | fd.write(line + "\n") 73 | probes_with_no_response = flags['probesent'] - len(hops) 74 | count += probes_with_no_response 75 | 76 | fd.close() 77 | print(">> Processed: %d probes" % count) 78 | print(">>", datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S')) 79 | 80 | if __name__ == "__main__": 81 | main() 82 | -------------------------------------------------------------------------------- /subnet.cpp: -------------------------------------------------------------------------------- 1 | #include "yarrp.h" 2 | #include "subnet.h" 3 | 4 | static uint32_t NETMASKS[] = { 5 | 0x00000000, 6 | 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 7 | 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000, 8 | 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, 9 | 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, 10 | 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, 11 | 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00, 12 | 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 13 | 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff 14 | }; 15 | 16 | Subnet::Subnet(string s) { 17 | uint32_t addr; 18 | uint8_t mask; 19 | char *p = strdup(s.c_str()); 20 | 21 | if (2 == sscanf(s.c_str(), "%[0-9.]/%hhu", p, &mask)) { 22 | addr = ntohl(inet_addr(p)); 23 | if (mask > 32) { 24 | start = end = offset = 0; 25 | fatal("Bad IPv4 subnet mask: %s", s.c_str()); 26 | } 27 | start = addr & NETMASKS[mask]; 28 | smask = mask; 29 | offset = 0; 30 | end = start + (1 << (32 - mask)); 31 | } else { 32 | fatal("Error parsing IPv4 subnet: %s", s.c_str()); 33 | } 34 | free(p); 35 | } 36 | 37 | Subnet6::Subnet6(string s, uint8_t granularity) { 38 | uint8_t m; 39 | char *p = strdup(s.c_str()); 40 | if (2 == sscanf(s.c_str(), "%[a-fA-F0-9:]/%hhu", p, &m)) { 41 | //cout << "Got IPv6 prefix: " << p << " mask: " << int (m) << endl; 42 | if (inet_pton(AF_INET6, p, &start) != 1) { 43 | fatal("Error parsing IPv6 address: %s", p); 44 | } 45 | smask = m; 46 | if (smask > 64) { 47 | fatal("IPv6 prefix must be at least /64 or larger!"); 48 | } 49 | cnt = 1 << (granularity-m); 50 | 51 | /* four 32-bits words in ipv6 address; which one is subnet boundary */ 52 | uint8_t boundary_word = m / 32; 53 | uint8_t boundary_mask = m % 32; 54 | char output[INET6_ADDRSTRLEN]; 55 | inet_ntop(AF_INET6, &start, output, INET6_ADDRSTRLEN); 56 | //cout << "Start: " << output << endl; 57 | //cout << "boundary word:" << (int) boundary_word << endl; 58 | //cout << "boundary mask:" << (int) boundary_mask << endl; 59 | for (int i=boundary_word+1; i<4; i++ ) { 60 | start.s6_addr32[i] = 0; 61 | } 62 | //printf("WORD: %08x\n", ntohl(start.s6_addr32[boundary_word])); 63 | //printf("MASK: %08x\n", NETMASKS[boundary_mask]); 64 | start.s6_addr32[boundary_word] = htonl( ntohl(start.s6_addr32[boundary_word]) & NETMASKS[boundary_mask] ); 65 | //printf("WORD: %08x\n", ntohl(start.s6_addr32[boundary_word])); 66 | inet_ntop(AF_INET6, &start, output, INET6_ADDRSTRLEN); 67 | //cout << "Start: " << output << endl; 68 | 69 | memcpy(&end, &start, sizeof(struct in6_addr)); 70 | for (int i=boundary_word+1; i<4; i++ ) { 71 | end.s6_addr32[i] += NETMASKS[32]; 72 | } 73 | end.s6_addr32[boundary_word] += htonl( (1 << (32-boundary_mask))-1); 74 | inet_ntop(AF_INET6, &end, output, INET6_ADDRSTRLEN); 75 | //cout << "End: " << output << endl; 76 | } else { 77 | fatal("Error parsing IPv6 subnet: %s", s.c_str()); 78 | } 79 | free(p); 80 | } 81 | 82 | Subnet::~Subnet() { 83 | } 84 | 85 | Subnet6::~Subnet6() { 86 | } 87 | 88 | uint32_t Subnet::first() { 89 | return start; 90 | } 91 | 92 | struct in6_addr *Subnet6::first() { 93 | return &start; 94 | } 95 | 96 | uint32_t Subnet::last() { 97 | return end - 1; 98 | } 99 | 100 | /* we iterate through /24's. so, count is number of /24s */ 101 | uint32_t Subnet::count() { 102 | return (end - start) >> 8; 103 | } 104 | -------------------------------------------------------------------------------- /ttlhisto.h: -------------------------------------------------------------------------------- 1 | /* TTL tree histogram; last time we've seen a new interface 2 | * at a given TTL 3 | */ 4 | #ifndef _TTLHISTO_H_ 5 | #define _TTLHISTO_H_ 6 | 7 | #include 8 | 9 | class TTLHisto { 10 | public: 11 | TTLHisto() : lastNew(0), lastSent(0), probes(0), prob_thresh(0.05) {}; 12 | void probed(uint32_t elapsed) { 13 | lastSent = elapsed; 14 | } 15 | /* If no new interface seen in past 5 minutes, we 16 | * stop probing at this TTL */ 17 | bool shouldProbe() { 18 | int32_t delta = lastSent - lastNew; 19 | if (delta > 30*1000) { 20 | //std::cout << "* Not probing TTL b/c TTL > 300*1000" << std::endl; 21 | return false; 22 | } 23 | return true; 24 | } 25 | virtual bool add(uint32_t src, uint32_t elapsed) { return false; }; 26 | virtual bool add(in6_addr *src, uint32_t elapsed) { return false; }; 27 | virtual bool shouldProbeProb() { return false; }; 28 | virtual void dump() = 0; 29 | 30 | protected: 31 | uint32_t lastNew; 32 | uint32_t lastSent; 33 | uint32_t probes; 34 | float prob_thresh; 35 | float prob; 36 | }; 37 | 38 | class TTLHisto4 : public TTLHisto { 39 | public: 40 | TTLHisto4() {}; 41 | void dump() { 42 | int32_t delta = lastSent - lastNew; 43 | std::cout << "Last new intf seen: " << lastNew << " sent: " << lastSent; 44 | std::cout << " delta: " << delta << std::endl; 45 | for (std::unordered_set::iterator iter = routers.begin(); 46 | iter != routers.end(); 47 | iter++) 48 | { 49 | struct in_addr sin; 50 | sin.s_addr = *iter; 51 | std::cout << "\t\t" << inet_ntoa(sin) << std::endl; 52 | } 53 | } 54 | bool add(uint32_t src, uint32_t elapsed) { 55 | probes++; 56 | if (routers.find(src) == routers.end()) { 57 | probes = routers.size() + 1; /* reset probes to parity */ 58 | routers.insert(src); 59 | lastNew = elapsed; 60 | return true; 61 | } 62 | return false; 63 | } 64 | bool shouldProbeProb() { 65 | prob = (float) routers.size() / probes; 66 | if (prob < prob_thresh) 67 | return false; 68 | return true; 69 | } 70 | 71 | private: 72 | std::unordered_set routers; 73 | }; 74 | 75 | class TTLHisto6 : public TTLHisto { 76 | public: 77 | TTLHisto6() { 78 | source = (char *) calloc(1, INET6_ADDRSTRLEN); 79 | }; 80 | void dump() { 81 | int32_t delta = lastSent - lastNew; 82 | std::cout << "Last new int: " << lastNew << " sent: " << lastSent; 83 | std::cout << " delta: " << delta; 84 | std::cout << " ints: " << routers.size() << "/" << probes << std::endl; 85 | for (std::unordered_set::iterator iter = routers.begin(); iter != routers.end(); iter++) 86 | { 87 | std::cout << "\t\t" << *iter << std::endl; 88 | } 89 | } 90 | bool add(in6_addr *src, uint32_t elapsed) { 91 | probes++; 92 | inet_ntop(AF_INET6, src->s6_addr, source, INET6_ADDRSTRLEN); 93 | if (routers.find(source) == routers.end()) { 94 | probes = routers.size() + 1; /* reset probes to parity */ 95 | routers.insert(source); 96 | lastNew = elapsed; 97 | return true; 98 | } 99 | return false; 100 | } 101 | /* look at ratio of discovered routers to probes at TTL */ 102 | bool shouldProbeProb() { 103 | prob = (float) routers.size() / probes; 104 | if (prob < prob_thresh) 105 | return false; 106 | return true; 107 | } 108 | 109 | private: 110 | std::unordered_set routers; 111 | char *source; 112 | }; 113 | 114 | #endif 115 | -------------------------------------------------------------------------------- /random_list.cpp: -------------------------------------------------------------------------------- 1 | #include "yarrp.h" 2 | #include "random_list.h" 3 | 4 | RandomSubnetList::RandomSubnetList(uint8_t _maxttl, uint8_t _gran):SubnetList(_maxttl, _gran) { 5 | seeded = false; 6 | perm = NULL; 7 | memset(key, 0, KEYLEN); 8 | } 9 | 10 | RandomSubnetList::~RandomSubnetList() { 11 | if (perm) 12 | cperm_destroy(perm); 13 | } 14 | 15 | void 16 | RandomSubnetList::seed() { 17 | PermMode mode = PERM_MODE_CYCLE; 18 | assert(addr_count > 0); 19 | 20 | if (addr_count < 500000) { 21 | mode = PERM_MODE_PREFIX; 22 | } 23 | //printf("%s: permsize: %d\n", __func__, addr_count); 24 | perm = cperm_create(addr_count, mode, PERM_CIPHER_RC5, key, 16); 25 | if (!perm) { 26 | printf("Failed to initialize permutation of size %u. Code: %d\n", addr_count, cperm_get_last_error()); 27 | exit(1); 28 | } 29 | seeded = true; 30 | } 31 | 32 | uint32_t 33 | RandomSubnetList::next_address(struct in_addr *in, uint8_t *ttl) { 34 | list < Subnet >::iterator iter; 35 | uint64_t next; 36 | uint32_t subnet_count, current = 0; 37 | uint32_t addr, offset; 38 | 39 | if (!seeded) 40 | seed(); 41 | 42 | if (PERM_END == cperm_next(perm, &next)) 43 | return 0; 44 | 45 | for (iter = subnets.begin(); iter != subnets.end(); iter++) { 46 | subnet_count = (*iter).count() * maxttl; 47 | if (next >= current && next < current + subnet_count) { 48 | offset = next - current; 49 | // LSB's encode the TTL 50 | *ttl = (offset & ttlmask) + 1; 51 | addr = (*iter).first() + (offset << (8 - ttlmask_bits)); 52 | addr = addr & 0xffffff00; 53 | addr += getHost((uint8_t *) &addr); 54 | in->s_addr = htonl(addr); 55 | return 1; 56 | } 57 | current += subnet_count; 58 | } 59 | return 1; 60 | } 61 | 62 | uint32_t 63 | RandomSubnetList::next_address(struct in6_addr *in, uint8_t * ttl) { 64 | list < Subnet6 >::iterator iter; 65 | uint64_t next = 0; 66 | uint32_t subnet_count, current = 0; 67 | uint32_t offset = 0; 68 | uint64_t high, iid = 0; 69 | 70 | if (!seeded) 71 | seed(); 72 | 73 | if (PERM_END == cperm_next(perm, &next)) 74 | return 0; 75 | 76 | for (iter = subnets6.begin(); iter != subnets6.end(); iter++) { 77 | subnet_count = (*iter).count() * maxttl; 78 | if (next >= current && next < current + subnet_count) { 79 | offset = next - current; 80 | *ttl = (offset & ttlmask); 81 | // upper bits are offset into subnet 82 | int subnetoffset = (offset >> ttlmask_bits); 83 | memcpy(in, (*iter).first(), sizeof(struct in6_addr)); 84 | //char output[INET6_ADDRSTRLEN]; 85 | //inet_ntop(AF_INET6, in, output, INET6_ADDRSTRLEN); 86 | //cout << "Using first as base: " << output << endl; 87 | 88 | high = (subnetoffset << (64-granularity)); 89 | (*in).s6_addr32[0] += htonl( (high & 0xFFFFFFFF00000000) >> 32); 90 | (*in).s6_addr32[1] += htonl( (high & 0x00000000FFFFFFFF)); 91 | 92 | #if 0 93 | iid = rndIID((uint32_t *)in); 94 | (*in).s6_addr32[2] += htonl( (iid & 0xFFFFFFFF00000000) >> 32); 95 | (*in).s6_addr32[3] += htonl( (iid & 0x00000000FFFFFFFF)); 96 | #else 97 | (*in).s6_addr32[3] = htonl(1); 98 | #endif 99 | return 1; 100 | } 101 | current += subnet_count; 102 | } 103 | return 1; 104 | } 105 | 106 | uint16_t 107 | RandomSubnetList::getHost(uint8_t *addr) { 108 | uint16_t sum = addr[0] + addr[1] + addr[2] + addr[3] + 127; 109 | return sum & 0xff; 110 | } 111 | 112 | uint64_t 113 | RandomSubnetList::rndIID(uint32_t *addr) { 114 | uint64_t sum = random(); 115 | sum = (sum<<32); 116 | sum += random() ^ (addr[0] + addr[1]); 117 | return sum; 118 | } 119 | -------------------------------------------------------------------------------- /util.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | Program: $Id: util.cpp 32 2015-01-10 23:05:29Z rbeverly $ 3 | Date: $Date: 2015-01-10 15:05:29 -0800 (Sat, 10 Jan 2015) $ 4 | Description: yarrp misc routines 5 | ****************************************************************************/ 6 | #include "yarrp.h" 7 | #include 8 | 9 | /** 10 | * Returns the number of milliseconds difference between 11 | * two struct timevals 12 | * 13 | * @param end timeval 14 | * @param begin timeval 15 | * @return milliseconds 16 | */ 17 | uint32_t 18 | tsdiff(struct timeval *end, struct timeval *begin) { 19 | uint32_t diff = (end->tv_sec - begin->tv_sec) * 1000; 20 | diff += (end->tv_usec - begin->tv_usec) / 1000; 21 | return diff; 22 | } 23 | 24 | uint32_t 25 | tsdiffus(struct timeval *end, struct timeval *begin) { 26 | uint32_t diff = (end->tv_sec - begin->tv_sec) * 1000000; 27 | diff += (end->tv_usec - begin->tv_usec); 28 | return diff; 29 | } 30 | 31 | double 32 | now(void) { 33 | struct timeval now; 34 | gettimeofday(&now, NULL); 35 | return (double)now.tv_sec + (double)now.tv_usec / 1000000.; 36 | } 37 | 38 | 39 | /** 40 | * Sigmoid function 41 | * http://en.wikipedia.org/wiki/Sigmoid_function 42 | */ 43 | double 44 | sigmoid(double t) { 45 | return 1.0 / (1.0 + exp(-t)); 46 | } 47 | 48 | /** 49 | * Probability of taking an action, given an input time (t) 50 | * and range over which to decay. Example: input milliseconds 51 | * with a decay from 1 to 0 over an hour timespan: 52 | * decayprob(t, 3600*1000) 53 | */ 54 | double 55 | decayprob(double t, uint32_t range) { 56 | t = t / (range / 12.0); 57 | t -= 6; 58 | return (1.0 - sigmoid(t)); 59 | } 60 | 61 | double 62 | decayprob(int32_t t, uint32_t range) { 63 | return (decayprob((double)t, range)); 64 | } 65 | 66 | uint8_t 67 | randuint8() { 68 | long val = random(); 69 | uint8_t *p = (uint8_t *) & val; 70 | return *(p + 3); 71 | } 72 | 73 | bool 74 | checkRoot() { 75 | if ((getuid() != 0) && (geteuid() != 0)) { 76 | cerr << "** requires root." << endl; 77 | exit(2); 78 | } 79 | return true; 80 | } 81 | 82 | double 83 | zrand() { 84 | static bool seeded = false; 85 | if (not seeded) { 86 | srand48((long)time(NULL)); 87 | seeded = true; 88 | } 89 | return drand48(); 90 | } 91 | 92 | /* generate a random libcperm key */ 93 | void permseed(uint8_t *key, uint32_t seed) { 94 | srand(seed); 95 | for (int i=0;i>= 1) { ++l; } 115 | return l; 116 | } 117 | 118 | /* Ensure that only one instance of Yarrp is running */ 119 | void instanceLock(uint8_t instance) { 120 | const char *homedir = getenv("HOME"); 121 | if (homedir) { 122 | char dotdir[1400]; 123 | snprintf(dotdir, 1400, "%s/.yarrp", homedir); 124 | struct stat st = {0}; 125 | if (stat(dotdir, &st) == -1) { 126 | mkdir(dotdir, 0755); 127 | } 128 | char lockfile[1500]; 129 | snprintf(lockfile, 1500, "%s/lock.%d", dotdir, instance); 130 | int fd = open(lockfile, O_CREAT | O_RDWR, 0644); 131 | struct flock lock; 132 | memset(&lock, 0, sizeof(lock)); 133 | lock.l_type = F_WRLCK; 134 | if (fcntl(fd, F_SETLK, &lock) < 0) { 135 | cerr << "*** " << __func__ << ": Yarrp instance already running." << endl; 136 | exit(-1); 137 | } 138 | } else { 139 | cerr << "*** " << __func__ << ": getenv" << endl; 140 | exit(-1); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # 2 | # $Id: configure.ac $ 3 | # 4 | 5 | AC_INIT([yarrp],[0.8],[yarrp@cmand.org]) 6 | AC_CONFIG_SRCDIR([yarrp.cpp]) 7 | AC_CONFIG_AUX_DIR([build-aux]) 8 | AM_INIT_AUTOMAKE([-Wall foreign subdir-objects]) 9 | AC_CONFIG_HEADERS([config.h]) 10 | AC_CONFIG_MACRO_DIR([m4]) 11 | AC_CANONICAL_HOST 12 | AC_PROG_CXX 13 | AC_LANG(C++) 14 | AX_CXX_COMPILE_STDCXX([17],[],[]) 15 | 16 | AC_REVISION([m4_esyscmd_s([git describe --always])]) 17 | AC_DEFINE(GITREV,"[m4_esyscmd_s([git describe --always])]", "Git revision") 18 | 19 | AX_PTHREAD([],AC_MSG_ERROR([Requires POSIX threading.])) 20 | LIBS="$PTHREAD_LIBS" 21 | CXXFLAGS="$PTHREAD_CFLAGS $CXXFLAGS -I/usr/local/include" 22 | LDFLAGS="-L/usr/local/lib" 23 | 24 | AX_CHECK_ZLIB 25 | 26 | AC_MSG_RESULT(Determined host operating system: $host_os) 27 | case $host_os in 28 | *linux*) 29 | AC_DEFINE(OS,"LINUX",[Operating System String]) 30 | AC_DEFINE(_LINUX,1,[Define to 1 if a Linux operating system]);; 31 | *freebsd*) 32 | AC_DEFINE(OS,"FBSD",[Operating System String]) 33 | AC_DEFINE(_BSD,1,[Define to 1 if a BSD-like operating system]) 34 | freebsd_version=$(uname -K) 35 | AX_COMPARE_VERSION($freebsd_version,[lt],[1100000], 36 | AC_DEFINE(_OLD_BSD,1,[Define to 1 if Freebsd<11]), 37 | AC_DEFINE(_NEW_FBSD,1,[Define to 1 if Freebsd>=11]));; 38 | *bsd*) 39 | AC_DEFINE(OS,"BSD",[Operating System String]) 40 | AC_DEFINE(_BSD,1,[Define to 1 if a BSD-like operating system]);; 41 | *darwin*) 42 | AC_DEFINE(OS,"OSX",[Operating System String]) 43 | AC_DEFINE(_BSD,1,[Define to 1 if a BSD-like operating system]) 44 | AC_DEFINE(_OSX,1,[Define to 1 if an Apple OSX operating system]);; 45 | *) 46 | AC_DEFINE(OS,"UNDEF",[Operating System String]);; 47 | esac 48 | 49 | # Checks for header files. 50 | AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h netdb.h]) 51 | AC_CHECK_HEADERS([inttypes.h],,AC_MSG_ERROR([required header file missing])) 52 | AC_CHECK_HEADERS([netinet/in.h stdint.h stdlib.h string.h strings.h]) 53 | AC_CHECK_HEADERS([sys/param.h sys/stat.h sys/types.h sys/socket.h unistd.h]) 54 | AC_CHECK_HEADERS([netinet/in_systm.h netinet/udp.h]) 55 | AC_CHECK_HEADERS([netinet/tcp.h]) 56 | AC_CHECK_HEADERS([netinet/ip.h netinet/ip_icmp.h netinet/ip_var.h], [], [], [ 57 | #ifdef HAVE_SYS_TYPES_H 58 | #include 59 | #endif 60 | #ifdef HAVE_NETINET_IN_SYSTM_H 61 | #include 62 | #endif 63 | #ifdef HAVE_NETINET_IN_H 64 | #include 65 | #endif 66 | ]) 67 | AC_CHECK_HEADERS([netinet/udp_var.h], [], [], [ 68 | #ifdef HAVE_SYS_TYPES_H 69 | #include 70 | #endif 71 | #ifdef HAVE_NETINET_IN_SYSTM_H 72 | #include 73 | #endif 74 | #ifdef HAVE_NETINET_IN_H 75 | #include 76 | #endif 77 | #ifdef HAVE_NETINET_UDP_H 78 | #include 79 | #endif 80 | #ifdef HAVE_NETINET_IP_H 81 | #include 82 | #endif 83 | ]) 84 | 85 | # Checks for typedefs, structures, and compiler characteristics. 86 | AC_TYPE_PID_T 87 | AC_TYPE_SIZE_T 88 | AC_TYPE_SSIZE_T 89 | AC_HEADER_STDBOOL 90 | AC_TYPE_UINT16_T 91 | AC_TYPE_UINT32_T 92 | AC_TYPE_UINT64_T 93 | AC_TYPE_UINT8_T 94 | 95 | AC_CACHE_CHECK(whether in_addr_t is defined, sip_cv_type_in_addr_t, 96 | [AC_EGREP_HEADER(in_addr_t, netinet/in.h, 97 | sip_cv_type_in_addr_t=yes, 98 | sip_cv_type_in_addr_t=no)]) 99 | 100 | if test $sip_cv_type_in_addr_t = yes; then 101 | AC_DEFINE(HAVE_IN_ADDR_T,1,[Define to 1 if type in_addr_t is available.]) 102 | fi[] 103 | 104 | # Check architecture endianness 105 | AC_C_BIGENDIAN 106 | if test "x$ac_cv_c_bigendian" = "xyes"; then 107 | AC_DEFINE(HAVE_BIG_ENDIAN,1,[Define to 1 for big endian, 0 otherwise.]) 108 | fi 109 | 110 | # Checks for library functions. 111 | AC_CHECK_FUNCS([inet_ntoa memset select socket strerror]) 112 | 113 | AC_SEARCH_LIBS([socket], [socket]) 114 | 115 | # Include pcap library on non-Linux systems 116 | # Don't need pcap on Linux since we can use recvfrom on raw socket 117 | AS_CASE([$host_os], [*linux*], , 118 | [AC_SEARCH_LIBS(pcap_close, pcap,, AC_MSG_ERROR(pcap library required))]) 119 | 120 | AC_CONFIG_FILES([ 121 | Makefile 122 | utils/Makefile 123 | ]) 124 | AC_OUTPUT 125 | -------------------------------------------------------------------------------- /listener.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | Program: $Id: listener.cpp 40 2016-01-02 18:54:39Z rbeverly $ 3 | Date: $Date: 2016-01-02 10:54:39 -0800 (Sat, 02 Jan 2016) $ 4 | Description: yarrp listener thread 5 | ****************************************************************************/ 6 | #include "yarrp.h" 7 | #include 8 | 9 | static volatile bool run = true; 10 | 11 | void intHandler(int dummy) { 12 | run = false; 13 | } 14 | 15 | void * 16 | listener(void *args) { 17 | fd_set rfds; 18 | Traceroute *trace = reinterpret_cast < Traceroute * >(args); 19 | struct timeval timeout; 20 | unsigned char buf[PKTSIZE]; 21 | uint32_t nullreads = 0; 22 | int n, len; 23 | TTLHisto *ttlhisto = NULL; 24 | uint32_t elapsed = 0; 25 | struct ip *ip = NULL; 26 | struct icmp *ippayload = NULL; 27 | int rcvsock; /* receive (icmp) socket file descriptor */ 28 | 29 | /* block until main thread says we're ready. */ 30 | trace->lock(); 31 | trace->unlock(); 32 | 33 | if ((rcvsock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) { 34 | cerr << "yarrp listener socket error:" << strerror(errno) << endl; 35 | } 36 | 37 | while (true) { 38 | if (nullreads >= MAXNULLREADS) 39 | break; 40 | timeout.tv_sec = 5; 41 | timeout.tv_usec = 0; 42 | FD_ZERO(&rfds); 43 | FD_SET(rcvsock, &rfds); 44 | n = select(rcvsock + 1, &rfds, NULL, NULL, &timeout); 45 | /* only timeout if we're also probing (not listen-only mode) */ 46 | if ((n == 0) and (trace->config->probe)) { 47 | nullreads++; 48 | cerr << ">> Listener: timeout " << nullreads; 49 | cerr << "/" << MAXNULLREADS << endl; 50 | continue; 51 | } 52 | if (n > 0) { 53 | nullreads = 0; 54 | memset(buf, 0, PKTSIZE); 55 | len = recv(rcvsock, buf, PKTSIZE, 0); 56 | if (len == -1) { 57 | cerr << ">> Listener: read error: " << strerror(errno) << endl; 58 | continue; 59 | } 60 | ip = (struct ip *)buf; 61 | if ((ip->ip_v == IPVERSION) and (ip->ip_p == IPPROTO_ICMP)) { 62 | ippayload = (struct icmp *)&buf[ip->ip_hl << 2]; 63 | elapsed = trace->elapsed(); 64 | ICMP *icmp = new ICMP4(ip, ippayload, elapsed, trace->config->coarse); 65 | if (verbosity > LOW) 66 | icmp->print(); 67 | /* ICMP message not from this yarrp instance, skip. */ 68 | if (icmp->getInstance() != trace->config->instance) { 69 | if (verbosity > HIGH) 70 | cerr << ">> Listener: packet instance mismatch." << endl; 71 | delete icmp; 72 | continue; 73 | } 74 | if (icmp->getSport() == 0) 75 | trace->stats->baddst+=1; 76 | /* Fill mode logic. */ 77 | if (trace->config->fillmode) { 78 | if ( (icmp->getTTL() >= trace->config->maxttl) and 79 | (icmp->getTTL() <= trace->config->fillmode) ) { 80 | uint32_t dst_ip = icmp->quoteDst(); 81 | if (dst_ip != 0) { 82 | trace->stats->fills+=1; 83 | trace->probe(icmp->quoteDst(), icmp->getTTL() + 1); 84 | } 85 | } 86 | } 87 | icmp->write(&(trace->config->out), trace->stats->count); 88 | #if 0 89 | Status *status = NULL; 90 | if (trace->tree != NULL) 91 | status = (Status *) trace->tree->get(icmp->quoteDst()); 92 | if (status) { 93 | status->result(icmp->quoteTTL(), elapsed); 94 | //status->print(); 95 | } 96 | #endif 97 | /* TTL tree histogram */ 98 | if (trace->ttlhisto.size() > icmp->quoteTTL()) { 99 | /* make certain we received a valid reply before adding */ 100 | if ( (icmp->getSport() != 0) and 101 | (icmp->getDport() != 0) ) 102 | { 103 | ttlhisto = trace->ttlhisto[icmp->quoteTTL()]; 104 | ttlhisto->add(icmp->getSrc(), elapsed); 105 | } 106 | } 107 | if (verbosity > DEBUG) 108 | trace->dumpHisto(); 109 | delete icmp; 110 | } 111 | } 112 | } 113 | return NULL; 114 | } 115 | -------------------------------------------------------------------------------- /yarrp.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (c) 2016-2024 Robert Beverly 3 | * All rights reserved. 4 | * 5 | * Attribution: R. Beverly, "Yarrp'ing the Internet: Randomized High-Speed 6 | * Active Topology Discovery", Proceedings of the ACM SIGCOMM 7 | * Internet Measurement Conference, November, 2016 8 | ***************************************************************************/ 9 | #if HAVE_CONFIG_H 10 | #include "config.h" 11 | #endif 12 | 13 | #ifndef _YRP_H_ 14 | #define _YRP_H_ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #ifndef __FAVOR_BSD 22 | #define __FAVOR_BSD 23 | #endif 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #ifdef _LINUX 32 | #include 33 | #endif 34 | #ifdef _BSD 35 | #include 36 | #include 37 | #endif 38 | #include 39 | #include 40 | #include 41 | 42 | #ifdef HAVE_NETINET_IP_VAR_H 43 | #include 44 | #endif 45 | #ifdef HAVE_NETINET_UDP_VAR_H 46 | #include 47 | #endif 48 | 49 | #include 50 | #include 51 | #include 52 | #ifdef HAVE_INTTYPES_H 53 | #include 54 | #endif 55 | #ifdef HAVE_STDINT_H 56 | #include 57 | #endif 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include 67 | 68 | #ifdef HAVE_PTHREAD 69 | #include 70 | #endif 71 | 72 | #include 73 | #include 74 | #include 75 | #include 76 | 77 | #include "libcperm/cperm.h" 78 | 79 | enum debugLevel {OFF, LOW, HIGH, DEBUG, DEVELOP}; 80 | typedef enum {TR_ICMP6, TR_ICMP, TR_UDP6, TR_UDP, 81 | TR_TCP6_SYN, TR_TCP_SYN, TR_TCP6_ACK, 82 | TR_TCP_ACK, TR_ICMP_REPLY} traceroute_type; 83 | 84 | static const char *Tr_Type_String[] = {"ICMP6", "ICMP", "UDP6", "UDP", 85 | "TCP6_SYN", "TCP_SYN", "TCP6_ACK", 86 | "TCP_ACK", "ICMP_REPLY"}; 87 | 88 | extern int verbosity; 89 | #define func() do {fprintf(stdout,"\t>> %s:%s():%d\n",__FILE__,__FUNCTION__,__LINE__); } while (0) 90 | #define warn(x...) do {fprintf(stderr,"*** Warn: "); fprintf(stderr,x); fprintf(stderr,"\n");} while (0) 91 | #define fatal(x...) do {fprintf(stderr,"*** Fatal: "); fprintf(stderr,x); fprintf(stderr,"\n"); exit(-1);} while (0) 92 | #define debug(level,x...) do {if (verbosity >= level) {std::cout << x << std::endl;} } while (0) 93 | #define PKTSIZE 1500 94 | #define MAXNULLREADS 10 95 | #define SHUTDOWN_WAIT 60 96 | //#define SHUTDOWN_WAIT 300 97 | #define KEYLEN 16 98 | #ifndef UINT8_MAX 99 | #define UINT8_MAX (255) 100 | #define UINT16_MAX (65535) 101 | #define UINT32_MAX (4294967295U) 102 | #endif 103 | #define ETH_HDRLEN 14 104 | 105 | /* IPv6 address manipulation */ 106 | #ifndef s6_addr16 107 | #define s6_addr16 __u6_addr.__u6_addr16 108 | #endif 109 | #ifndef s6_addr32 110 | #define s6_addr32 __u6_addr.__u6_addr32 111 | #endif 112 | 113 | unsigned short in_cksum(unsigned short *addr, int len); 114 | int infer_my_ip(struct sockaddr_in *mei); 115 | int infer_my_ip6(struct sockaddr_in6 *mei6); 116 | int raw_sock(struct sockaddr_in *sin_orig); 117 | int raw_sock6(struct sockaddr_in6 *sin6_orig); 118 | u_short p_cksum(struct ip *ip, u_short *data, int len); 119 | u_short p_cksum(struct ip6_hdr *ip, u_short *data, int len); 120 | unsigned short compute_data(unsigned short start_cksum, unsigned short target_cksum); 121 | void print_binary(const unsigned char *buf, int len, int brk, int tabs); 122 | void *listener(void *args); 123 | void *listener6(void *args); 124 | uint32_t tsdiff(struct timeval *end, struct timeval *begin); 125 | uint32_t tsdiffus(struct timeval *end, struct timeval *begin); 126 | double now(void); 127 | uint8_t randuint8(); 128 | bool checkRoot(); 129 | void instanceLock(uint8_t); 130 | double decayprob(double t, uint32_t range); 131 | double decayprob(int32_t t, uint32_t range); 132 | double zrand(); 133 | void permseed(uint8_t *); 134 | void permseed(uint8_t *, uint32_t); 135 | double poisson_pmf(const double k, const double lambda); 136 | uint32_t intlog(uint32_t in); 137 | int bpfget(); 138 | 139 | #include "yconfig.h" 140 | #include "patricia.h" 141 | #include "mac.h" 142 | #include "stats.h" 143 | #include "status.h" 144 | #include "ttlhisto.h" 145 | #include "subnet_list.h" 146 | #include "random_list.h" 147 | #include "trace.h" 148 | #include "icmp.h" 149 | 150 | void internet(YarrpConfig *config, Traceroute *trace, Patricia *tree, Stats *stats); 151 | void internet6(YarrpConfig *config, Traceroute *trace, Patricia *tree, Stats *stats); 152 | 153 | using namespace std; 154 | 155 | #endif /* _YRP_H_ */ 156 | -------------------------------------------------------------------------------- /libcperm/cperm.c: -------------------------------------------------------------------------------- 1 | /* ------------------------------------------------------------------------ 2 | libcperm - A library for creating random cpermutations. 3 | Copyright (c) 2014, Lance Alt 4 | 5 | This file is part of libcperm. 6 | 7 | This library is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Lesser General Public License as published 9 | by the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License 18 | along with this library. If not, see . 19 | ------------------------------------------------------------------------ 20 | */ 21 | 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "cperm.h" 30 | #include "cperm-internal.h" 31 | #include "prefix.h" 32 | #include "cycle.h" 33 | #include "ciphers/rc5.h" 34 | #include "ciphers/speck.h" 35 | 36 | int cperm_errno = 0; 37 | 38 | /* List of available cpermutation modes. Each mode has an identifier, and four functions. See ModeFuncs struct for description of the fields. */ 39 | static struct ModeFuncs available_modes[] = { 40 | { PERM_MODE_PREFIX, perm_prefix_create, perm_prefix_next, perm_prefix_get, perm_prefix_destroy }, 41 | { PERM_MODE_CYCLE, perm_cycle_create, perm_cycle_next, perm_cycle_get, perm_cycle_destroy }, 42 | { PERM_MODE_ERROR, NULL, NULL } 43 | }; 44 | 45 | /* List of available ciphers. Each cipher has an identifier, and four functions. See CipherFuncs struct for description of the fields. */ 46 | static struct CipherFuncs available_ciphers[] = { 47 | { PERM_CIPHER_RC5, perm_rc5_create, perm_rc5_enc, perm_rc5_dec, perm_rc5_destroy }, 48 | { PERM_CIPHER_SPECK, perm_speck_create, perm_speck_enc, perm_speck_dec, perm_speck_destroy }, 49 | { PERM_CIPHER_ERROR, NULL, NULL, NULL }, 50 | }; 51 | 52 | struct cperm_t* cperm_create(uint64_t range, PermMode m, PermCipher a, uint8_t* key, int key_len) { 53 | struct cperm_t* perm = calloc(sizeof(*perm), 1); 54 | if(!perm) { 55 | cperm_errno = PERM_ERROR_NOMEM; 56 | return NULL; 57 | } 58 | 59 | perm->range = range; 60 | 61 | /* Locate the selected mode and initialize function pointers */ 62 | struct ModeFuncs* mf = available_modes; 63 | while(mf->mode != PERM_MODE_ERROR) { 64 | if(mf->mode == m) { 65 | perm->mode = mf; 66 | break; 67 | } 68 | mf++; 69 | } 70 | if(perm->mode == NULL) { 71 | free(perm); 72 | cperm_errno = PERM_ERROR_MODE_NOT_SUPP; 73 | return NULL; 74 | } 75 | 76 | /* Locate the selected cipher and initialize function pointers */ 77 | struct CipherFuncs* cf = available_ciphers; 78 | while(cf->algo != PERM_CIPHER_ERROR) { 79 | if(cf->algo == a) { 80 | perm->cipher = cf; 81 | break; 82 | } 83 | cf++; 84 | } 85 | 86 | /* Set the cipher key */ 87 | cperm_set_key(perm, key, key_len); 88 | 89 | /* Initialize the cipher */ 90 | if(0 != perm->cipher->create(perm)) { 91 | free(perm); 92 | return NULL; 93 | } 94 | 95 | /* Initialize the cpermutation mode */ 96 | if(0 != perm->mode->create(perm)) { 97 | perm->cipher->destroy(perm); 98 | free(perm); 99 | return NULL; 100 | } 101 | 102 | return perm; 103 | } 104 | 105 | int cperm_set_key(struct cperm_t* perm, const unsigned char* key, uint16_t length) { 106 | if(!perm) { return PERM_ERROR_BAD_HANDLE; } 107 | 108 | if(perm->cipher) { 109 | perm->cipher->destroy(perm); 110 | } 111 | 112 | perm->key = malloc(length); 113 | memcpy(perm->key, key, length); 114 | perm->key_len = length; 115 | 116 | return 0; 117 | } 118 | 119 | void cperm_destroy(struct cperm_t* perm) { 120 | if(perm) { 121 | perm->mode->destroy(perm); 122 | perm->cipher->destroy(perm); 123 | if(perm->key) { 124 | free(perm->key); 125 | } 126 | free(perm); 127 | } 128 | } 129 | 130 | int cperm_next(struct cperm_t* perm, uint64_t* ct) { 131 | if(!perm) { return PERM_ERROR_BAD_HANDLE; } 132 | perm->position++; 133 | return perm->mode->next(perm, ct); 134 | } 135 | 136 | int cperm_enc(struct cperm_t* perm, uint64_t pt, uint64_t* ct) { 137 | if(!perm) { return PERM_ERROR_BAD_HANDLE; } 138 | return perm->mode->get(perm, pt, ct); 139 | } 140 | 141 | uint64_t cperm_dec(struct cperm_t* cperm, uint64_t pt) { 142 | return 0; 143 | } 144 | 145 | int cperm_get_last_error() { 146 | return cperm_errno; 147 | } 148 | 149 | int cperm_reset(struct cperm_t* perm) { 150 | if(!perm) { return PERM_ERROR_BAD_HANDLE; } 151 | 152 | perm->mode->destroy(perm); 153 | perm->mode->create(perm); 154 | return 1; 155 | } 156 | 157 | uint64_t cperm_get_range(const struct cperm_t* perm) { 158 | if(!perm) { return 0; } 159 | return perm->range; 160 | } 161 | 162 | uint64_t cperm_get_position(const struct cperm_t* perm) { 163 | if(!perm) { return 0; } 164 | return perm->position; 165 | } 166 | 167 | 168 | -------------------------------------------------------------------------------- /utils/yarrpfile.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2016-2019, Robert Beverly 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 are met: 8 | # * Redistributions of source code must retain the above copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # * Neither the name of the nor the 14 | # names of its contributors may be used to endorse or promote products 15 | # derived from this software without specific prior written permission. 16 | # 17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AN 18 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | # DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 21 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | # 28 | # Program: $Id: yarrpfile.py 1551 2015-02-11 14:14:09Z rbeverly $ 29 | # Author: Robert Beverly 30 | # Description: Python class to process Yarrp output 31 | # 32 | import bz2 33 | import gzip 34 | 35 | # from yarrp/src/trace.h 36 | traceroute_type = ["ICMP6", "ICMP", "UDP6", "UDP", "TCP6_SYN", "TCP_SYN", "TCP6_ACK", "TCP_ACK"] 37 | 38 | # from scamper/trace/scamper_trace.h 39 | tracetypemap = {'ICMP' : 0x04, 'ICMP6' : 0x04, 40 | 'UDP' : 0x05, 'UDP6' : 0x05, 41 | 'TCP_SYN' : 0x03, 'TCP6_SYN' : 0x03, 42 | 'TCP_ACK' : 0x06, 'TCP6_ACK' : 0x06 } 43 | 44 | class Yarrp: 45 | def __init__(self, yarrpfile, verbose=False): 46 | self.yarrpfile = yarrpfile 47 | self.verbose = verbose 48 | self.vantage_point = "undefined" 49 | self.us_granularity = False 50 | self.tracetype = None 51 | self.maxttl = -1 52 | self.columns = 0 53 | self.fillttl = 0 54 | self.fills = 0 55 | self.packets = 0 56 | self.start = "unknown" 57 | self.end = "unknown" 58 | self.open() 59 | 60 | def open(self): 61 | # try reading as a bz2 file 62 | try: 63 | self.fd = bz2.BZ2File(self.yarrpfile, 'rb') 64 | self.fd.read(1) 65 | self.fd = bz2.BZ2File(self.yarrpfile, 'rb') 66 | return 67 | except IOError, e: 68 | pass 69 | # try reading as a gzip file 70 | try: 71 | self.fd = gzip.open(self.yarrpfile, 'rb') 72 | self.fd.read(1) 73 | self.fd = gzip.open(self.yarrpfile, 'rb') 74 | return 75 | except IOError, e: 76 | pass 77 | # try reading as uncompressed 78 | self.fd = open(self.yarrpfile, 'rb') 79 | 80 | def next(self): 81 | assert(self.fd) 82 | line = self.fd.readline() 83 | if len(line) == 0: 84 | return False 85 | if line[0] == '#' and line.find(':') != -1: 86 | try: 87 | (key, value) = line[2:].strip().split(': ') 88 | #print "Key:", key, "Value:", value 89 | if key == "Trace_Type": 90 | self.tracetype = tracetypemap[value] 91 | if key == "SourceIP": 92 | self.vantage_point = value 93 | if key == "RTT_Granularity": 94 | if value == "us": 95 | self.us_granularity = True 96 | else: 97 | self.us_granularity = False 98 | if key == "Max_TTL": 99 | self.maxttl = int(value) 100 | if key == "Start": 101 | self.start = value 102 | if key == "Fill_Mode": 103 | self.filttl = int(value) 104 | if key == "Fills": 105 | self.fills = int(value) 106 | if key == 'Pkts': 107 | self.packets = int(value) 108 | except Exception, e: 109 | print "Error (next):", e 110 | print "line:", line 111 | pass 112 | return self.next() 113 | fields = line.strip().split() 114 | r = dict() 115 | if not self.columns: self.columns = len(fields) 116 | if len(fields) != self.columns: 117 | return False 118 | try: 119 | # new format 120 | if self.columns == 14: 121 | (r['target'], r['sec'], r['usec'], r['typ'], r['code'], 122 | r['ttl'], r['hop'], r['rtt'], r['ipid'], r['psize'], 123 | r['rsize'], r['rttl'], r['rtos'], r['count']) = fields 124 | for field in ['sec', 'usec', 'typ', 'code', 'ttl', 'rttl', 'rtt', 'psize', 'rsize', 'ipid', 'rtos']: 125 | r[field] = int(r[field]) 126 | if 'count' in r: 127 | r['count'] = int(r['count']) 128 | # Ugh, occassionally the recorded rtt is impossible... 129 | rtt = r['rtt'] 130 | if self.us_granularity == True: 131 | rtt = rtt/1000.0 132 | if rtt < 0 or rtt > 4294967295: rtt = 0 133 | r['rtt'] = rtt 134 | except ValueError, e: 135 | print "ERR:", e, ":", line, "expecting:", self.columns 136 | return r 137 | -------------------------------------------------------------------------------- /entire.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Description: Special code for fast, entire Internet-wide IPv6 probing 3 | ****************************************************************************/ 4 | #include "yarrp.h" 5 | 6 | /* SPECK 48/96 implementation */ 7 | #define MASK24 0xFFFFFF 8 | #define SPECK_ROUNDS 23 9 | #define SPECK_KEYLEN 4 10 | #define ROR(x, r) ((x >> r) | (x << (24 - r))&MASK24)&MASK24 11 | #define ROL(x, r) ((x << r) | (x >> (24 - r))&MASK24)&MASK24 12 | #define R(x, y, k) (x = ROR(x, 8), x = (x + y)&MASK24, x ^= k, y = ROL(y, 3), y ^= x) 13 | #define RR(x, y, k) (y ^= x, y = ROR(y, 3), x ^= k, x = (x - y)&MASK24, x = ROL(x, 8)) 14 | 15 | void speck_48_96_expand(uint32_t const K[SPECK_KEYLEN], uint32_t S[SPECK_ROUNDS]) 16 | { 17 | uint32_t i, b = K[0]; 18 | uint32_t a[SPECK_KEYLEN - 1]; 19 | 20 | for (i = 0; i < (SPECK_KEYLEN - 1); i++) 21 | { 22 | a[i] = K[i + 1]; 23 | } 24 | S[0] = b; 25 | for (i = 0; i < SPECK_ROUNDS - 1; i++) { 26 | R(a[i % (SPECK_KEYLEN - 1)], b, i); 27 | S[i + 1] = b; 28 | } 29 | } 30 | 31 | void speck_48_96_encrypt(uint32_t const pt[2], uint32_t ct[2], uint32_t const K[SPECK_ROUNDS]) 32 | { 33 | uint32_t i; 34 | ct[0]=pt[0]; ct[1]=pt[1]; 35 | 36 | for(i = 0; i < SPECK_ROUNDS; i++){ 37 | R(ct[1], ct[0], K[i]); 38 | } 39 | } 40 | 41 | 42 | /* Use 48 bits speck cipher: 43 | * prefix = 44 bits 44 | * ttl = 4 bits 45 | * Assume global unicast is 2000:/4, thus we generate candidate /48 prefixes 46 | */ 47 | void internet6(YarrpConfig *config, Traceroute *trace, Patricia *tree, Stats *stats) { 48 | uint8_t ttl; 49 | double prob, flip; 50 | uint64_t range = 0xFFFFFFFFFFFF; 51 | uint32_t buffer[2] = {0}; 52 | uint32_t exp[SPECK_ROUNDS]; 53 | uint32_t key[4] = {0x020100, 0x0a0908, 0x121110, 0x1a1918}; 54 | uint32_t plain[2]; 55 | struct in6_addr addr; 56 | char addrstring[INET6_ADDRSTRLEN]; 57 | TTLHisto *ttlhisto = NULL; 58 | 59 | memset(&addr, 0, sizeof(struct in6_addr)); 60 | speck_48_96_expand(key, exp); 61 | 62 | #if 0 63 | uint8_t iana8[6] = {0x20, 0x24, 0x26, 0x28, 0x2a, 0x2c}; 64 | uint16_t iana16[9] = {htons(0x2001), htons(0x2003), htons(0x2400), htons(0x2600), 65 | htons(0x2610), htons(0x2620), htons(0x2800), htons(0x2a00), 66 | htons(0x2c00)}; 67 | #endif 68 | 69 | for (uint64_t i = 0; i> 24; 72 | speck_48_96_encrypt(plain, buffer, exp); 73 | /* magic ensues */ 74 | addr.s6_addr[0] = 0x20 | (buffer[0] & 0xF); 75 | if ((addr.s6_addr[0] & 0x1) == 1) { 76 | stats->bgp_outside++; 77 | continue; 78 | } 79 | if (addr.s6_addr[0] == 0x22) { 80 | stats->bgp_outside++; 81 | continue; 82 | } 83 | if (addr.s6_addr[0] == 0x2e) { 84 | stats->bgp_outside++; 85 | continue; 86 | } 87 | addr.s6_addr[1] = (buffer[0] >> 4) & 0xFF; 88 | /* allow only 2800::/12, 2a00::/12, 2c00::/12 */ 89 | if ((addr.s6_addr[0] >= 0x28) and ((addr.s6_addr[1] & 0xF0) != 0)) { 90 | stats->bgp_outside++; 91 | continue; 92 | } 93 | /* allow only 2001:: and 2003:: */ 94 | if ((addr.s6_addr[0] == 0x20) and ((addr.s6_addr[1] & 0xFD) != 1)) { 95 | stats->bgp_outside++; 96 | continue; 97 | } 98 | if ((addr.s6_addr[0] == 0x24) and ((addr.s6_addr[1] & 0xF0) != 0)) { 99 | stats->bgp_outside++; 100 | continue; 101 | } 102 | 103 | addr.s6_addr[2] = (buffer[0] >> 12) & 0xFF; 104 | addr.s6_addr[3] = ((buffer[0] >> 20) & 0xF) << 4; 105 | addr.s6_addr[3] |= buffer[1] & 0xF; 106 | addr.s6_addr[4] = (buffer[1] >> 4) & 0xFF; 107 | addr.s6_addr[5] = (buffer[1] >> 12) & 0xFF; 108 | #if 1 109 | if (tree->get(addr) == NULL) { 110 | stats->bgp_outside++; 111 | continue; 112 | } 113 | #endif 114 | /* set bottom 32 bits to determinstic value of addr */ 115 | addr.s6_addr32[3] = (addr.s6_addr[0] + addr.s6_addr[1]) << 5; 116 | addr.s6_addr32[3] += addr.s6_addr[4]; 117 | addr.s6_addr[15] = addr.s6_addr[2] + addr.s6_addr[3] + 100; 118 | ttl = ((buffer[1] >> 20) & 0xF) + 1; 119 | #if 0 120 | inet_ntop(AF_INET6, &addr, addrstring, INET6_ADDRSTRLEN); 121 | printf("Addr: %s TTL: %d\n", addrstring, ttl); 122 | #endif 123 | #if 1 124 | if (ttl < config->ttl_neighborhood) { 125 | ttlhisto = trace->ttlhisto[ttl]; 126 | if (ttlhisto->shouldProbe() == false) { 127 | stats->nbr_skipped++; 128 | continue; 129 | } 130 | ttlhisto->probed(trace->elapsed()); 131 | } 132 | #endif 133 | /* Running w/ a biased TTL probability distribution */ 134 | if (config->poisson) { 135 | prob = poisson_pmf(ttl, config->poisson); 136 | flip = zrand(); 137 | if (flip > prob) 138 | continue; 139 | } 140 | trace->probe(addr, ttl); 141 | stats->count++; 142 | if (stats->count == config->count) 143 | break; 144 | /* Every 4096, do this */ 145 | if ( (stats->count & 0xFFF) == 0xFFF ) { 146 | stats->dump(stderr); 147 | if (config->rate) { 148 | /* Calculate sleep time based on scan rate */ 149 | usleep( (1000000 / config->rate) * 4096 ); 150 | } 151 | } 152 | } 153 | } 154 | 155 | -------------------------------------------------------------------------------- /libcperm/ciphers/rc5-16.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File: rc5-16.c 3 | * Author: zvrba 4 | * Created: 2008-04-08 5 | * 6 | * =========================================================================== 7 | * COPYRIGHT (c) 2008 Zeljko Vrba 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a 10 | * copy of this software and associated documentation files (the "Software"), 11 | * to deal in the Software without restriction, including without limitation 12 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | * and/or sell copies of the Software, and to permit persons to whom the 14 | * Software is furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in 17 | * all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | * DEALINGS IN THE SOFTWARE. 26 | * =========================================================================== 27 | */ 28 | /** 29 | * @file 30 | * 31 | * RC5 with 16-bit word size (= 32-bit block size). One of few ciphers (the 32 | * only?) which supports so small block size. This is practical because MIPS 33 | * addressing is also in 32-bit words. Implementation is based on RFC2040, 34 | * with some details changed to make it truly independent of the word size. 35 | */ 36 | 37 | #include "rc5-16.h" 38 | 39 | #if _MSC_VER < 1600 40 | #define inline __inline 41 | #endif 42 | 43 | #define WSZ 16 /* word size */ 44 | #define WW (WSZ/8) /* wsz in bytes */ 45 | #define BSZ (2*WW) /* block size */ 46 | #define BB (BSZ/8) /* bsz in bytes */ 47 | #define b RC5_KEYLEN /* key size in bytes */ 48 | #define R RC5_ROUNDS /* # of rounds */ 49 | #define T (2*(R+1)) /* # of words in expanded key table */ 50 | #define LL ((b+WW-1)/WW) /* # of elts in L (helper array) */ 51 | #define P ((RC5_WORD)0xB7E1) /* magic1: (e-2)*(2**W), e=nat log base */ 52 | #define Q ((RC5_WORD)0x9E37) /* magic2: (phi-1)*(2**W), phi=golden r.*/ 53 | /* Magic constants must be odd; add 1 if the 54 | * formula yields even. */ 55 | 56 | #if RC5_BLOCKSZ != BSZ 57 | #error "Mismatch between header and source parameters." 58 | #endif 59 | 60 | /** Rotate left by n bits. */ 61 | static inline RC5_WORD rol(RC5_WORD x, RC5_WORD n) 62 | { 63 | n &= (WSZ-1); 64 | return (x << n) | (x >> (WSZ-n)); 65 | } 66 | 67 | /** Rotate right by n bits. */ 68 | static inline RC5_WORD ror(RC5_WORD x, RC5_WORD n) 69 | { 70 | n &= (WSZ-1); 71 | return (x >> n) | (x << (WSZ-n)); 72 | } 73 | 74 | void rc5_setup(struct rc5_key *ks) 75 | { 76 | #define K(i) ((RC5_WORD)ks->key[i]) 77 | #define S(i) (ks->S[i]) 78 | int i, j, k, t; 79 | RC5_WORD A, B, L[LL]; 80 | 81 | for(i = 0; i < LL; i++) 82 | L[i] = 0; 83 | for(i = 0; i < b; i++) { 84 | t = K(i) << (8*(i % WW)); 85 | L[i/WW] = L[i/WW] | t; 86 | } 87 | 88 | S(0) = P; 89 | for(i = 1; i < T; i++) 90 | S(i) = S(i-1) + Q; 91 | 92 | i = j = 0; 93 | A = B = 0; 94 | if(LL > T) 95 | k = 3*LL; 96 | else 97 | k = 3*T; 98 | for(; k > 0; k--) { 99 | A = rol(S(i)+A+B, 3); 100 | S(i) = A; 101 | B = rol(L[j]+A+B, A+B); 102 | L[j] = B; 103 | i = (i+1) % T; 104 | j = (j+1) % LL; 105 | } 106 | #undef K 107 | #undef S 108 | } 109 | 110 | void rc5_ecb_encrypt(const struct rc5_key *ks, void *srcv, void *dstv) 111 | { 112 | #define S(i) (ks->S[i]) 113 | unsigned char *src = (unsigned char *)srcv; 114 | unsigned char *dst = (unsigned char *)dstv; 115 | 116 | RC5_WORD A = (src[0] | (src[1] << 8)) + S(0); 117 | RC5_WORD B = (src[2] | (src[3] << 8)) + S(1); 118 | int i; 119 | 120 | for(i = 1; i <= R; i++) { 121 | A = rol(A^B, B) + S(2*i); 122 | B = rol(B^A, A) + S(2*i+1); 123 | } 124 | 125 | dst[0] = A & 0xFF; 126 | dst[1] = A >> 8; 127 | dst[2] = B & 0xFF; 128 | dst[3] = B >> 8; 129 | #undef S 130 | } 131 | 132 | void rc5_ecb_decrypt(const struct rc5_key *ks, void *srcv, void *dstv) 133 | { 134 | #define S(i) (ks->S[i]) 135 | unsigned char *src = (unsigned char *)srcv; 136 | unsigned char *dst = (unsigned char *)dstv; 137 | 138 | RC5_WORD B = (src[3] << 8) | src[2]; 139 | RC5_WORD A = (src[1] << 8) | src[0]; 140 | int i; 141 | 142 | for(i = R; i > 0; i--) { 143 | B = ror(B-S(2*i+1), A) ^ A; 144 | A = ror(A-S(2*i), B) ^ B; 145 | } 146 | B -= S(1); 147 | A -= S(0); 148 | 149 | dst[3] = B >> 8; 150 | dst[2] = B & 0xFF; 151 | dst[1] = A >> 8; 152 | dst[0] = A & 0xFF; 153 | #undef S 154 | } 155 | 156 | #ifdef RC5_TEST 157 | 158 | #include 159 | 160 | /* This test is replicated from rc5ref.c. */ 161 | 162 | int main(void) 163 | { 164 | RC5_WORD pt1[2], pt2[2], ct[2] = { 0, 0 }; 165 | struct rc5_key key; 166 | int i, j; 167 | 168 | for(i = 1; i < 6; i++) { 169 | pt1[0] = ct[0]; 170 | pt1[1] = ct[1]; 171 | 172 | for(j = 0; j < b; j++) 173 | key.key[j] = ct[0] % (255-j); 174 | 175 | rc5_setup(&key); 176 | rc5_ecb_encrypt(&key, pt1, ct); 177 | rc5_ecb_decrypt(&key, ct, pt2); 178 | 179 | printf("%d. key = ", i); 180 | for(j = 0; j < b; j++) 181 | printf("%.2X ", key.key[j]); 182 | printf("\n"); 183 | 184 | printf("PT %.4hX %.4hX -> CT %.4hX %.4hX -> PT %.4hX %.4hX\n", 185 | pt1[0], pt1[1], ct[0], ct[1], pt2[0], pt2[1]); 186 | if((pt1[0] != pt2[0]) || (pt1[1] != pt2[1])) 187 | printf("DECRYPTION ERROR!\n"); 188 | printf("\n"); 189 | } 190 | 191 | return 0; 192 | } 193 | 194 | #endif /* RC5_TEST */ 195 | -------------------------------------------------------------------------------- /m4/ax_check_zlib.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_check_zlib.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_ZLIB([action-if-found], [action-if-not-found]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # This macro searches for an installed zlib library. If nothing was 12 | # specified when calling configure, it searches first in /usr/local and 13 | # then in /usr, /opt/local and /sw. If the --with-zlib=DIR is specified, 14 | # it will try to find it in DIR/include/zlib.h and DIR/lib/libz.a. If 15 | # --without-zlib is specified, the library is not searched at all. 16 | # 17 | # If either the header file (zlib.h) or the library (libz) is not found, 18 | # shell commands 'action-if-not-found' is run. If 'action-if-not-found' is 19 | # not specified, the configuration exits on error, asking for a valid zlib 20 | # installation directory or --without-zlib. 21 | # 22 | # If both header file and library are found, shell commands 23 | # 'action-if-found' is run. If 'action-if-found' is not specified, the 24 | # default action appends '-I${ZLIB_HOME}/include' to CPFLAGS, appends 25 | # '-L$ZLIB_HOME}/lib' to LDFLAGS, prepends '-lz' to LIBS, and calls 26 | # AC_DEFINE(HAVE_LIBZ). You should use autoheader to include a definition 27 | # for this symbol in a config.h file. Sample usage in a C/C++ source is as 28 | # follows: 29 | # 30 | # #ifdef HAVE_LIBZ 31 | # #include 32 | # #endif /* HAVE_LIBZ */ 33 | # 34 | # LICENSE 35 | # 36 | # Copyright (c) 2008 Loic Dachary 37 | # Copyright (c) 2010 Bastien Chevreux 38 | # 39 | # This program is free software; you can redistribute it and/or modify it 40 | # under the terms of the GNU General Public License as published by the 41 | # Free Software Foundation; either version 2 of the License, or (at your 42 | # option) any later version. 43 | # 44 | # This program is distributed in the hope that it will be useful, but 45 | # WITHOUT ANY WARRANTY; without even the implied warranty of 46 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 47 | # Public License for more details. 48 | # 49 | # You should have received a copy of the GNU General Public License along 50 | # with this program. If not, see . 51 | # 52 | # As a special exception, the respective Autoconf Macro's copyright owner 53 | # gives unlimited permission to copy, distribute and modify the configure 54 | # scripts that are the output of Autoconf when processing the Macro. You 55 | # need not follow the terms of the GNU General Public License when using 56 | # or distributing such scripts, even though portions of the text of the 57 | # Macro appear in them. The GNU General Public License (GPL) does govern 58 | # all other use of the material that constitutes the Autoconf Macro. 59 | # 60 | # This special exception to the GPL applies to versions of the Autoconf 61 | # Macro released by the Autoconf Archive. When you make and distribute a 62 | # modified version of the Autoconf Macro, you may extend this special 63 | # exception to the GPL to apply to your modified version as well. 64 | 65 | #serial 14 66 | 67 | AU_ALIAS([CHECK_ZLIB], [AX_CHECK_ZLIB]) 68 | AC_DEFUN([AX_CHECK_ZLIB], 69 | # 70 | # Handle user hints 71 | # 72 | [AC_MSG_CHECKING(if zlib is wanted) 73 | zlib_places="/usr/local /usr /opt/local /sw" 74 | AC_ARG_WITH([zlib], 75 | [ --with-zlib=DIR root directory path of zlib installation @<:@defaults to 76 | /usr/local or /usr if not found in /usr/local@:>@ 77 | --without-zlib to disable zlib usage completely], 78 | [if test "$withval" != no ; then 79 | AC_MSG_RESULT(yes) 80 | if test -d "$withval" 81 | then 82 | zlib_places="$withval $zlib_places" 83 | else 84 | AC_MSG_WARN([Sorry, $withval does not exist, checking usual places]) 85 | fi 86 | else 87 | zlib_places= 88 | AC_MSG_RESULT(no) 89 | fi], 90 | [AC_MSG_RESULT(yes)]) 91 | 92 | # 93 | # Locate zlib, if wanted 94 | # 95 | if test -n "${zlib_places}" 96 | then 97 | # check the user supplied or any other more or less 'standard' place: 98 | # Most UNIX systems : /usr/local and /usr 99 | # MacPorts / Fink on OSX : /opt/local respectively /sw 100 | for ZLIB_HOME in ${zlib_places} ; do 101 | if test -f "${ZLIB_HOME}/include/zlib.h"; then break; fi 102 | ZLIB_HOME="" 103 | done 104 | 105 | ZLIB_OLD_LDFLAGS=$LDFLAGS 106 | ZLIB_OLD_CPPFLAGS=$CPPFLAGS 107 | if test -n "${ZLIB_HOME}"; then 108 | LDFLAGS="$LDFLAGS -L${ZLIB_HOME}/lib" 109 | CPPFLAGS="$CPPFLAGS -I${ZLIB_HOME}/include" 110 | fi 111 | AC_LANG_PUSH([C++]) 112 | AC_LANG([C]) 113 | AC_CHECK_LIB([z], [inflateEnd], [zlib_cv_libz=yes], [zlib_cv_libz=no]) 114 | AC_CHECK_HEADER([zlib.h], [zlib_cv_zlib_h=yes], [zlib_cv_zlib_h=no]) 115 | AC_LANG_POP([]) 116 | if test "$zlib_cv_libz" = "yes" && test "$zlib_cv_zlib_h" = "yes" 117 | then 118 | # 119 | # If both library and header were found, action-if-found 120 | # 121 | m4_ifblank([$1],[ 122 | CPPFLAGS="$CPPFLAGS -I${ZLIB_HOME}/include" 123 | LDFLAGS="$LDFLAGS -L${ZLIB_HOME}/lib" 124 | LIBS="-lz $LIBS" 125 | AC_DEFINE([HAVE_LIBZ], [1], 126 | [Define to 1 if you have `z' library (-lz)]) 127 | ],[ 128 | # Restore variables 129 | LDFLAGS="$ZLIB_OLD_LDFLAGS" 130 | CPPFLAGS="$ZLIB_OLD_CPPFLAGS" 131 | $1 132 | ]) 133 | else 134 | # 135 | # If either header or library was not found, action-if-not-found 136 | # 137 | m4_default([$2],[ 138 | AC_MSG_ERROR([either specify a valid zlib installation with --with-zlib=DIR or disable zlib usage with --without-zlib]) 139 | ]) 140 | fi 141 | fi 142 | ]) 143 | 144 | -------------------------------------------------------------------------------- /iplist.cpp: -------------------------------------------------------------------------------- 1 | #include "yarrp.h" 2 | #include "random_list.h" 3 | 4 | IPList::IPList(uint8_t _maxttl, bool _rand, bool _entire) : seeded(false) { 5 | perm = NULL; 6 | permsize = 0; 7 | maxttl = _maxttl; 8 | ttlbits = intlog(maxttl); 9 | ttlmask = 0xffffffff >> (32 - ttlbits); 10 | ttlprefix = ttlmask ^ 0xff; 11 | rand = _rand; 12 | entire = _entire; 13 | if (entire) 14 | permsize = UINT32_MAX; 15 | memset(key, 0, KEYLEN); 16 | } 17 | 18 | void IPList::setkey(int seed) { 19 | debug(HIGH, ">> Seed: " << seed); 20 | permseed(key, seed); 21 | } 22 | 23 | IPList4::~IPList4() { 24 | targets.clear(); 25 | cperm_destroy(perm); 26 | } 27 | 28 | IPList6::~IPList6() { 29 | targets.clear(); 30 | cperm_destroy(perm); 31 | } 32 | 33 | /* seed */ 34 | void IPList4::seed() { 35 | PermMode mode = PERM_MODE_CYCLE; 36 | if (not entire) { 37 | assert(targets.size() > 0); 38 | permsize = targets.size() * maxttl; 39 | if (permsize < 1000000) 40 | mode = PERM_MODE_PREFIX; 41 | } 42 | perm = cperm_create(permsize, mode, PERM_CIPHER_RC5, key, 16); 43 | assert(perm); 44 | seeded = true; 45 | } 46 | 47 | void IPList6::seed() { 48 | PermMode mode = PERM_MODE_PREFIX; 49 | assert(targets.size() > 0); 50 | permsize = targets.size() * maxttl; 51 | if (permsize > 5000000) { 52 | mode = PERM_MODE_CYCLE; 53 | std::cout << ">> Warning: reduced IPv6 performance with this many targets" << std::endl; 54 | std::cout << ">> use fewer targets, or lower max TTL (-m)" << std::endl; 55 | } 56 | perm = cperm_create(permsize, mode, PERM_CIPHER_SPECK, key, 8); 57 | assert(perm); 58 | seeded = true; 59 | } 60 | 61 | /* Read list of input IPs */ 62 | void IPList::read(char *in) { 63 | if (*in == '-') { 64 | read(std::cin); 65 | } else { 66 | std::ifstream ifile(in); 67 | if (ifile.good() == false) 68 | fatal("Bad input file: %s", in); 69 | read(ifile); 70 | } 71 | } 72 | 73 | /* Read list of input IPs */ 74 | void IPList4::read(std::istream& inlist) { 75 | std::string line; 76 | struct in_addr addr; 77 | while (getline(inlist, line)) { 78 | if (!line.empty() && line[line.size() - 1] == '\r') 79 | line.erase( std::remove(line.begin(), line.end(), '\r'), line.end() ); 80 | if (inet_aton(line.c_str(), &addr) != 1) 81 | fatal("Couldn't parse IPv4 address: %s", line.c_str()); 82 | targets.push_back(addr.s_addr); 83 | } 84 | debug(LOW, ">> IPv4 targets: " << targets.size()); 85 | } 86 | 87 | /* Read list of input IPs */ 88 | void IPList6::read(std::istream& inlist) { 89 | std::string line; 90 | struct in6_addr addr; 91 | while (getline(inlist, line)) { 92 | if (!line.empty() && line[line.size() - 1] == '\r') 93 | line.erase( std::remove(line.begin(), line.end(), '\r'), line.end() ); 94 | if (inet_pton(AF_INET6, line.c_str(), &addr) != 1) 95 | fatal("Couldn't parse IPv6 address: %s", line.c_str()); 96 | targets.push_back(addr); 97 | } 98 | debug(LOW, ">> IPv6 targets: " << targets.size()); 99 | } 100 | 101 | uint32_t IPList4::next_address(struct in_addr *in, uint8_t * ttl) { 102 | if (entire) 103 | return next_address_entire(in, ttl); 104 | else if (rand) 105 | return next_address_rand(in, ttl); 106 | else 107 | return next_address_seq(in, ttl); 108 | } 109 | 110 | /* sequential next address */ 111 | uint32_t IPList4::next_address_seq(struct in_addr *in, uint8_t * ttl) { 112 | static std::vector::iterator iter = targets.begin(); 113 | static uint32_t last_addr = *iter; 114 | static uint8_t last_ttl = 0; 115 | 116 | if (last_ttl + 1 > maxttl) { 117 | iter++; 118 | if (iter == targets.end()) 119 | return 0; 120 | last_ttl = 0; 121 | last_addr = *(iter); 122 | } 123 | *ttl = last_ttl; 124 | last_ttl+=1; 125 | in->s_addr = last_addr; 126 | return 1; 127 | } 128 | 129 | /* random next address */ 130 | uint32_t IPList4::next_address_rand(struct in_addr *in, uint8_t * ttl) { 131 | static uint64_t next = 0; 132 | static uint32_t next32 = 0; 133 | 134 | if (not seeded) 135 | seed(); 136 | 137 | if (PERM_END == cperm_next(perm, &next)) 138 | return 0; 139 | next32 = next % 0xffffffff; 140 | in->s_addr = targets[next32 >> ttlbits]; 141 | if (ttlbits == 0) 142 | *ttl = 0; 143 | else 144 | *ttl = (next32 & ttlmask); 145 | return 1; 146 | } 147 | 148 | /* Internet-wide scanning mode */ 149 | uint32_t IPList4::next_address_entire(struct in_addr *in, uint8_t * ttl) { 150 | static uint64_t next = 0; 151 | static uint32_t next32 = 0; 152 | static uint32_t host; 153 | static char *p; 154 | 155 | if (not seeded) 156 | seed(); 157 | 158 | p = (char *) &next; 159 | while (PERM_END != cperm_next(perm, &next)) { 160 | next32 = next % 0xffffffff; 161 | *ttl = next32 >> 24; // use remaining 8 bits of perm as ttl 162 | if ( (*ttl & ttlprefix) != 0x0) { // fast check: ttls in [0,31] 163 | continue; 164 | } 165 | in->s_addr = next32 & 0x00FFFFFF; // pick out 24 bits of network 166 | host = (p[0] + p[1] + p[2]) & 0xFF; 167 | in->s_addr += (host << 24); 168 | return 1; 169 | } 170 | return 0; 171 | } 172 | 173 | uint32_t IPList6::next_address(struct in6_addr *in, uint8_t * ttl) { 174 | if (rand) 175 | return next_address_rand(in, ttl); 176 | else 177 | return next_address_seq(in, ttl); 178 | } 179 | 180 | /* sequential next address */ 181 | uint32_t IPList6::next_address_seq(struct in6_addr *in, uint8_t * ttl) { 182 | static std::vector::iterator iter = targets.begin(); 183 | static struct in6_addr last_addr = *iter; 184 | static uint8_t last_ttl = 0; 185 | int i; 186 | 187 | if (last_ttl + 1 > maxttl) { 188 | iter++; 189 | if (iter == targets.end()) 190 | return 0; 191 | last_ttl = 0; 192 | last_addr = *(iter); 193 | } 194 | *ttl = last_ttl; 195 | for(i = 0; i < 16; i++) 196 | in->s6_addr[i] = last_addr.s6_addr[i]; 197 | last_ttl+=1; 198 | return 1; 199 | } 200 | 201 | /* random next address */ 202 | uint32_t IPList6::next_address_rand(struct in6_addr *in, uint8_t * ttl) { 203 | static uint64_t next = 0; 204 | 205 | if (not seeded) 206 | seed(); 207 | 208 | if (PERM_END == cperm_next(perm, &next)) 209 | return 0; 210 | 211 | *in = targets[next >> ttlbits]; 212 | *ttl = (next & ttlmask); 213 | return 1; 214 | } 215 | -------------------------------------------------------------------------------- /mac.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | Program: $Id: net.cpp 14 2014-12-30 02:33:44Z laalt $ 3 | Date: $Date: 2014-12-29 18:33:44 -0800 (Mon, 29 Dec 2014) $ 4 | Description: networking routines 5 | ****************************************************************************/ 6 | #include "yarrp.h" 7 | 8 | char *LLResolv::mac2str(char *mac) { 9 | static char buf[BUFSIZE]; 10 | snprintf(buf, BUFSIZE, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", 11 | mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 12 | return buf; 13 | } 14 | 15 | int LLResolv::print_gw() { 16 | char buf[INET6_ADDRSTRLEN]; 17 | 18 | if (inet_ntop(AF_INET, &(gw.ip), buf, INET6_ADDRSTRLEN) == NULL) 19 | return -1; 20 | printf("IPv4 gateway: %s\n", buf); 21 | printf("IPv4 gateway mac: %s\n", mac2str(gw.mac)); 22 | if (inet_ntop(AF_INET6, &(gw.ip6), buf, INET6_ADDRSTRLEN) == NULL) 23 | return -1; 24 | printf("IPv6 gateway: %s\n", buf); 25 | printf("IPv6 gateway mac: %s\n", mac2str(gw.mac6)); 26 | return 0; 27 | } 28 | 29 | void LLResolv::setDstMAC(uint8_t **mac) { 30 | *mac = (uint8_t *)calloc(6, sizeof(uint8_t)); 31 | memcpy(*mac, gw.mac6, ETH_ALEN); 32 | } 33 | 34 | #ifdef _LINUX 35 | void LLResolv::mine(const char *interface) { 36 | if ((sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) { 37 | printf("PF_PACKET error: %s\n", strerror(errno)); 38 | exit(-1); 39 | } 40 | memset (&ifr, 0, sizeof (ifr)); 41 | snprintf (ifr.ifr_name, sizeof (ifr.ifr_name), "%s", interface); 42 | ioctl (sock, SIOCGIFHWADDR, &ifr); 43 | close(sock); 44 | } 45 | #else 46 | void LLResolv::mine(const char *interface) {}; 47 | #endif 48 | 49 | #ifdef _LINUX 50 | void LLResolv::gateway() { 51 | char buf[BUFSIZE]; 52 | 53 | if ((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) <= 0) { 54 | printf("PF_NETLINK error: %s\n", strerror(errno)); 55 | exit(-1); 56 | } 57 | size_t nlseq = send_req(buf, nlseq, RTM_GETROUTE); 58 | size_t msg_len = read_res(buf, nlseq); 59 | struct nlmsghdr *nlmsg = reinterpret_cast(buf); 60 | for (; NLMSG_OK(nlmsg, msg_len); nlmsg = NLMSG_NEXT(nlmsg, msg_len)) 61 | parse_route(nlmsg); 62 | nlseq = send_req(buf, nlseq, RTM_GETNEIGH); 63 | msg_len = read_res(buf, nlseq); 64 | nlmsg = reinterpret_cast(buf); 65 | for (; NLMSG_OK(nlmsg, msg_len); nlmsg = NLMSG_NEXT(nlmsg, msg_len)) 66 | parse_neigh(nlmsg); 67 | close(sock); 68 | } 69 | #else 70 | void LLResolv::gateway() { 71 | fatal("Non-linux IPv6 requires specifying source (-M) and gateway (-G) MAC"); 72 | }; 73 | #endif 74 | 75 | #ifdef _LINUX 76 | void LLResolv::setSrcMAC(uint8_t **mac) { 77 | *mac = (uint8_t *)calloc(6, sizeof(uint8_t)); 78 | memcpy(*mac, ifr.ifr_hwaddr.sa_data, ETH_ALEN); 79 | } 80 | void LLResolv::print_self() { 81 | printf("Host mac: %s\n", mac2str(ifr.ifr_hwaddr.sa_data)); 82 | } 83 | #else 84 | void LLResolv::setSrcMAC(uint8_t **mac) {}; 85 | void LLResolv::print_self() {}; 86 | #endif 87 | 88 | #ifdef _LINUX 89 | int LLResolv::send_req(char *buf, size_t nlseq, size_t req_type) { 90 | memset(buf, 0, BUFSIZE); 91 | struct nlmsghdr * nlmsg = reinterpret_cast(buf); 92 | nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); 93 | nlmsg->nlmsg_type = req_type; 94 | nlmsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; 95 | nlmsg->nlmsg_seq = nlseq++; 96 | nlmsg->nlmsg_pid = getpid(); 97 | 98 | if (send(sock, buf, nlmsg->nlmsg_len, 0) < 0) 99 | return -1; 100 | 101 | return nlseq; 102 | } 103 | 104 | int LLResolv::read_res(char *buf, size_t nlseq) { 105 | struct nlmsghdr *nlmsg; 106 | int len; 107 | size_t total_len = 0; 108 | 109 | do { 110 | if ((len = recv(sock, buf, BUFSIZE - total_len, 0)) < 0) 111 | return -1; 112 | 113 | nlmsg = reinterpret_cast(buf); 114 | 115 | if (NLMSG_OK(nlmsg, len) == 0) 116 | return -1; 117 | if (nlmsg->nlmsg_type == NLMSG_ERROR) 118 | return -1; 119 | if (nlmsg->nlmsg_type == NLMSG_DONE) 120 | break; 121 | 122 | buf += len; 123 | total_len += len; 124 | 125 | if ((nlmsg->nlmsg_flags & NLM_F_MULTI) == 0) 126 | break; 127 | 128 | } while (nlmsg->nlmsg_seq != nlseq || nlmsg->nlmsg_pid != getpid()); 129 | 130 | return total_len; 131 | } 132 | 133 | void LLResolv::parse_route(struct nlmsghdr *nlmsg) { 134 | struct gw_info *info = &gw; 135 | 136 | struct rtmsg *rtmsg = reinterpret_cast(NLMSG_DATA(nlmsg)); 137 | if (rtmsg->rtm_table != RT_TABLE_MAIN) 138 | return; 139 | 140 | struct rtattr *attr = reinterpret_cast(RTM_RTA(rtmsg)); 141 | size_t len = RTM_PAYLOAD(nlmsg); 142 | 143 | for (; RTA_OK(attr, len); attr = RTA_NEXT(attr, len)) { 144 | if (attr->rta_type != RTA_GATEWAY) 145 | continue; 146 | if (rtmsg->rtm_family == AF_INET) 147 | info->ip = *reinterpret_cast(RTA_DATA(attr)); 148 | else if (rtmsg->rtm_family == AF_INET6) 149 | memcpy(info->ip6, RTA_DATA(attr), IPV6SIZE); 150 | break; 151 | } 152 | } 153 | 154 | void LLResolv::parse_neigh(struct nlmsghdr *nlmsg) { 155 | char mac[ETH_ALEN]; 156 | uint32_t ip = 0; 157 | char ip6[IPV6SIZE]; 158 | struct gw_info *info = &gw; 159 | 160 | struct ndmsg *ndmsg = reinterpret_cast(NLMSG_DATA(nlmsg)); 161 | struct rtattr *attr = reinterpret_cast(RTM_RTA(ndmsg)); 162 | size_t len = RTM_PAYLOAD(nlmsg); 163 | 164 | for (; RTA_OK(attr, len); attr = RTA_NEXT(attr, len)) { 165 | if (attr->rta_type == NDA_LLADDR) 166 | memcpy(mac, RTA_DATA(attr), ETH_ALEN); 167 | 168 | if (ndmsg->ndm_family == AF_INET && attr->rta_type == NDA_DST) 169 | ip = *reinterpret_cast(RTA_DATA(attr)); 170 | 171 | if (ndmsg->ndm_family == AF_INET6 && attr->rta_type == NDA_DST) 172 | memcpy(ip6, RTA_DATA(attr), IPV6SIZE); 173 | } 174 | 175 | if (ndmsg->ndm_family == AF_INET && ip && ip == info->ip) 176 | memcpy(info->mac, mac, ETH_ALEN); 177 | 178 | if (ndmsg->ndm_family == AF_INET6) { 179 | if (memcmp(ip6, info->ip6, IPV6SIZE) == 0) 180 | memcpy(info->mac6, mac, ETH_ALEN); 181 | } 182 | } 183 | #endif 184 | -------------------------------------------------------------------------------- /listener6.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | Program: $Id: listener.cpp 40 2016-01-02 18:54:39Z rbeverly $ 3 | Date: $Date: 2016-01-02 10:54:39 -0800 (Sat, 02 Jan 2016) $ 4 | Description: yarrp listener thread 5 | ****************************************************************************/ 6 | #include "yarrp.h" 7 | #include 8 | 9 | static volatile bool run = true; 10 | void intHandler(int dummy); 11 | 12 | #ifndef _LINUX 13 | int bpfinit(char *dev, size_t *bpflen) { 14 | int rcvsock = -1; 15 | 16 | debug(DEVELOP, ">> Listener6 BPF"); 17 | rcvsock = bpfget(); 18 | if (rcvsock < 0) fatal("bpf open error\n"); 19 | struct ifreq bound_if; 20 | strcpy(bound_if.ifr_name, dev); 21 | if (ioctl(rcvsock, BIOCSETIF, &bound_if) > 0) fatal("ioctl err\n"); 22 | uint32_t enable = 1; 23 | if (ioctl(rcvsock, BIOCSHDRCMPLT, &enable) <0) fatal("ioctl err\n"); 24 | if (ioctl(rcvsock, BIOCIMMEDIATE, &enable) <0) fatal("ioctl err\n"); 25 | struct bpf_program fcode = {0}; 26 | struct bpf_insn insns[] = { 27 | BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12), 28 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_IPV6, 0, 3), 29 | BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 20), 30 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IPPROTO_ICMPV6, 0, 1), 31 | BPF_STMT(BPF_RET+BPF_K, (u_int)-1), 32 | BPF_STMT(BPF_RET+BPF_K, 0), 33 | }; 34 | fcode.bf_len = sizeof(insns) / sizeof(struct bpf_insn); 35 | fcode.bf_insns = &insns[0]; 36 | if(ioctl(rcvsock, BIOCSETF, &fcode) < 0) fatal("set filter\n"); 37 | ioctl(rcvsock, BIOCGBLEN, bpflen); 38 | return rcvsock; 39 | } 40 | #endif 41 | 42 | void *listener6(void *args) { 43 | fd_set rfds; 44 | Traceroute6 *trace = reinterpret_cast < Traceroute6 * >(args); 45 | struct timeval timeout; 46 | unsigned char *buf = (unsigned char *) calloc(1,PKTSIZE); 47 | uint32_t nullreads = 0; 48 | int n, len; 49 | TTLHisto *ttlhisto = NULL; 50 | uint32_t elapsed = 0; 51 | struct ip6_hdr *ip = NULL; /* IPv6 hdr */ 52 | struct icmp6_hdr *ippayload = NULL; /* ICMP6 hdr */ 53 | int rcvsock; /* receive (icmp) socket file descriptor */ 54 | 55 | /* block until main thread says we're ready. */ 56 | trace->lock(); 57 | trace->unlock(); 58 | 59 | #ifdef _LINUX 60 | if ((rcvsock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) { 61 | cerr << "yarrp listener socket error:" << strerror(errno) << endl; 62 | } 63 | 64 | /* bind PF_PACKET to single interface */ 65 | struct ifreq ifr; 66 | strncpy(ifr.ifr_name, trace->config->int_name, IFNAMSIZ); 67 | if (ioctl(rcvsock, SIOCGIFINDEX, &ifr) < 0) fatal ("ioctl err");; 68 | struct sockaddr_ll sll; 69 | memset(&sll, 0, sizeof(sll)); 70 | sll.sll_family = PF_PACKET; 71 | sll.sll_protocol = htons(ETH_P_ALL); 72 | sll.sll_ifindex = ifr.ifr_ifindex; 73 | if (bind(rcvsock, (struct sockaddr*) &sll, sizeof(sll)) < 0) { 74 | fatal("Bind to PF_PACKET socket"); 75 | } 76 | #else 77 | /* Init BPF */ 78 | size_t blen = 0; 79 | rcvsock = bpfinit(trace->config->int_name, &blen); 80 | unsigned char *bpfbuf = (unsigned char *) calloc(1,blen); 81 | struct bpf_hdr *bh = NULL; 82 | #endif 83 | 84 | signal(SIGINT, intHandler); 85 | while (true and run) { 86 | if (nullreads >= MAXNULLREADS) 87 | break; 88 | #ifdef _LINUX 89 | timeout.tv_sec = 5; 90 | timeout.tv_usec = 0; 91 | FD_ZERO(&rfds); 92 | FD_SET(rcvsock, &rfds); 93 | n = select(rcvsock + 1, &rfds, NULL, NULL, &timeout); 94 | if (n == 0) { 95 | nullreads++; 96 | cerr << ">> Listener: timeout " << nullreads; 97 | cerr << "/" << MAXNULLREADS << endl; 98 | continue; 99 | } 100 | if (n == -1) { 101 | fatal("select error"); 102 | } 103 | nullreads = 0; 104 | memset(buf, 0, PKTSIZE); 105 | len = recv(rcvsock, buf, PKTSIZE, 0); 106 | #else 107 | memset(bpfbuf, 0, blen); 108 | len = read(rcvsock, bpfbuf, blen); 109 | unsigned char *p = bpfbuf; 110 | reloop: 111 | bh = (struct bpf_hdr *)p; 112 | buf = p + bh->bh_hdrlen; /* realign buf */ 113 | #endif 114 | if (len == -1) { 115 | fatal("%s %s", __func__, strerror(errno)); 116 | } 117 | ip = (struct ip6_hdr *)(buf + ETH_HDRLEN); 118 | if (ip->ip6_nxt == IPPROTO_ICMPV6) { 119 | ippayload = (struct icmp6_hdr *)&buf[ETH_HDRLEN + sizeof(struct ip6_hdr)]; 120 | elapsed = trace->elapsed(); 121 | if ( (ippayload->icmp6_type == ICMP6_TIME_EXCEEDED) or 122 | (ippayload->icmp6_type == ICMP6_DST_UNREACH) or 123 | (ippayload->icmp6_type == ICMP6_ECHO_REPLY) ) { 124 | ICMP *icmp = new ICMP6(ip, ippayload, elapsed, trace->config->coarse); 125 | if (icmp->is_yarrp) { 126 | if (verbosity > LOW) 127 | icmp->print(); 128 | if (icmp->getInstance() != trace->config->instance) { 129 | if (verbosity > HIGH) 130 | cerr << ">> Listener: packet instance mismatch." << endl; 131 | delete icmp; 132 | continue; 133 | } 134 | /* Fill mode logic. */ 135 | if (trace->config->fillmode) { 136 | if ( (icmp->getTTL() >= trace->config->maxttl) and 137 | (icmp->getTTL() < trace->config->fillmode) ) { 138 | trace->stats->fills+=1; 139 | trace->probe(icmp->quoteDst6(), icmp->getTTL() + 1); 140 | } 141 | } 142 | icmp->write(&(trace->config->out), trace->stats->count); 143 | /* TTL tree histogram */ 144 | if (trace->ttlhisto.size() > icmp->quoteTTL()) { 145 | ttlhisto = trace->ttlhisto[icmp->quoteTTL()]; 146 | ttlhisto->add(icmp->getSrc6(), elapsed); 147 | } 148 | if (verbosity > DEBUG) 149 | trace->dumpHisto(); 150 | } 151 | delete icmp; 152 | } 153 | } 154 | #ifndef _LINUX 155 | p += BPF_WORDALIGN(bh->bh_hdrlen + bh->bh_caplen); 156 | if (p < bpfbuf + len) goto reloop; 157 | #endif 158 | } 159 | return NULL; 160 | } 161 | -------------------------------------------------------------------------------- /libcperm/cperm.h: -------------------------------------------------------------------------------- 1 | /* ------------------------------------------------------------------------ 2 | libcperm - A library for creating random permutations. 3 | Copyright (c) 2014, Lance Alt 4 | 5 | This file is part of libcperm. 6 | 7 | This library is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Lesser General Public License as published 9 | by the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License 18 | along with this library. If not, see . 19 | ------------------------------------------------------------------------ 20 | */ 21 | 22 | /** 23 | * @file perm.h 24 | * @author Lance Alt 25 | * @date 24 July 2014 26 | * @brief libperm API 27 | * 28 | */ 29 | #ifndef PERM_H 30 | #define PERM_H 31 | 32 | #include 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | // General errors 39 | #define PERM_ERROR_UNKNOWN -1 40 | #define PERM_ERROR_BAD_HANDLE -2 // cperm_t was not valid 41 | #define PERM_ERROR_NOMEM -3 // failed to allocate memory 42 | #define PERM_ERROR_RANGE -4 // requested item was outside permutation range 43 | #define PERM_END -5 // when calling next(), at the end of the permutation 44 | 45 | // Key related errors 46 | #define PERM_ERROR_NOKEY -10 // no key was set 47 | #define PERM_ERROR_BAD_KEY_LENGTH -11 // key was incorrect length for particular cipher 48 | 49 | // Cipher related errors 50 | #define PERM_ERROR_CIPHER_NOT_SUPP -20 // cipher not supported 51 | 52 | // Mode related errors 53 | #define PERM_ERROR_MODE_NOT_SUPP -30 // mode not supported 54 | #define PERM_ERROR_OP_NOT_SUPP -31 // operation not supported in this mode 55 | 56 | /** 57 | * @brief Permutation mode to use. 58 | * 59 | * Enumerate to select which type of permutation mode to use. Available options are: 60 | */ 61 | typedef enum { PERM_MODE_ERROR = -1, 62 | PERM_MODE_AUTO, /**< Automatically select the mode to use based on permutation size */ 63 | PERM_MODE_PREFIX, /**< Use prefix cipher mode */ 64 | PERM_MODE_CYCLE, /**< Use cycle walking mode */ 65 | PERM_MODE_FEISTEL /**< Use Feistel mode (currently not implemented) */ 66 | } PermMode; 67 | 68 | typedef enum { PERM_CIPHER_ERROR = -1, 69 | PERM_CIPHER_AUTO, // Automatically select cipher to user (only RC5 is currently implemented) 70 | PERM_CIPHER_RC5, // Use the RC5 cipher 71 | PERM_CIPHER_SPECK, // Use the Speck cipher 72 | } PermCipher; 73 | 74 | struct ccperm_t; 75 | 76 | extern int cperm_errno; 77 | 78 | /** 79 | * @brief Create a new permutation. 80 | * 81 | * Create a new permutation of the given range. The permutation will contain items between 82 | * 0 and @c range. The permutation mode can be selected using the @mode parameter or selected 83 | * automatically using the @c PERM_MODE_AUTO option. The cipher to use is selected using the 84 | * @c cipher parameter or automatically selected using the @c PERM_CIPHER_AUTO option. 85 | * 86 | * @param range Size of the permutation. Maximum of 2^32. 87 | * @param mode Permutation generation mode to use. 88 | * @param cipher Cipher to use. 89 | * @param key Cipher key. 90 | * @param key_len Length of the cipher key passed in @p key. 91 | * 92 | * @return Returns a pointer to @c cperm_t or error. 93 | */ 94 | struct cperm_t* cperm_create(uint64_t range, PermMode m, PermCipher a, uint8_t* key, int key_len); 95 | 96 | /** 97 | * @brief Destroy a permutation object. 98 | * 99 | * All resources used by the permutation object will be freed and the object will become 100 | * invalid. 101 | * 102 | * @param p Permutation object to destroy. 103 | */ 104 | void cperm_destroy(struct cperm_t* p); 105 | 106 | int cperm_set_key(struct cperm_t* perm, const unsigned char* key, uint16_t length); 107 | 108 | /** 109 | * @brief Get the next item in the permutation. 110 | * 111 | * Newly created permutations start at index zero. Each call to @c perm_next returns the 112 | * next permutation item in succession until the end of permutation is reached. 113 | * 114 | * @param p Permutation object 115 | * @param ct Pointer to an integer to store the next permutation value 116 | * 117 | * @return 0 on success or @c PERM_END when there are no more items in the permutation. 118 | */ 119 | int cperm_next(struct cperm_t* p, uint64_t* ct); 120 | 121 | /** 122 | * @brief Encodes an index to its permuted value. 123 | * 124 | * Note: This API call is not supported on all permutation modes. At present, this 125 | * function is only supported when using @c PERM_MODE_PREFIX. Calling this function 126 | * when using a different mode will return @c PERM_ERROR_OP_NOT_SUPP. 127 | * 128 | * @param p The permutation object 129 | * @param pt Index within the permutation 130 | * @param ct Pointer to an integer to store the permuted value 131 | * 132 | * @return 0 on success or error code on failure. 133 | */ 134 | int cperm_enc(struct cperm_t* perm, uint64_t pt, uint64_t* ct); 135 | 136 | /** 137 | * @brief Returns the error status of the last API function. 138 | * 139 | * Most API calls return an error code directly. Some functions however, do not return 140 | * specific errors and must be checked explicitly using this function. The following 141 | * functions must be explicitly checked for error conditions: 142 | * - @c perm_create 143 | * - @c perm_get_position 144 | * - @c perm_get_range 145 | * 146 | * @return Last API error or PERM_OK if the last API call was successful. 147 | */ 148 | int cperm_get_last_error(); 149 | 150 | /** 151 | * @brief Returns the range of a permutation object. 152 | * 153 | * @param p The permutation object 154 | * 155 | * @return Length of the permutation or 0 on error. 156 | */ 157 | uint64_t cperm_get_range(const struct cperm_t* p); 158 | 159 | /** 160 | * @brief Returns the current position of a permutation object. 161 | * 162 | * @param p The permutation object 163 | * 164 | * @return Current position of the permutation or 0 on error. 165 | */ 166 | uint64_t cperm_get_position(const struct cperm_t* p); 167 | 168 | /** 169 | * @brief Resets the position of the permutation back to 0. 170 | * 171 | * @param p The permutation object 172 | * 173 | * @return 0 on success or @c PERM_ERROR_BAD_HANDLE if the object is invalid. 174 | */ 175 | int cperm_reset(struct cperm_t* perm); 176 | 177 | #ifdef __cplusplus 178 | }; 179 | #endif 180 | 181 | #endif /* PERM_H */ 182 | -------------------------------------------------------------------------------- /m4/ax_compare_version.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_compare_version.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_COMPARE_VERSION(VERSION_A, OP, VERSION_B, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # This macro compares two version strings. Due to the various number of 12 | # minor-version numbers that can exist, and the fact that string 13 | # comparisons are not compatible with numeric comparisons, this is not 14 | # necessarily trivial to do in a autoconf script. This macro makes doing 15 | # these comparisons easy. 16 | # 17 | # The six basic comparisons are available, as well as checking equality 18 | # limited to a certain number of minor-version levels. 19 | # 20 | # The operator OP determines what type of comparison to do, and can be one 21 | # of: 22 | # 23 | # eq - equal (test A == B) 24 | # ne - not equal (test A != B) 25 | # le - less than or equal (test A <= B) 26 | # ge - greater than or equal (test A >= B) 27 | # lt - less than (test A < B) 28 | # gt - greater than (test A > B) 29 | # 30 | # Additionally, the eq and ne operator can have a number after it to limit 31 | # the test to that number of minor versions. 32 | # 33 | # eq0 - equal up to the length of the shorter version 34 | # ne0 - not equal up to the length of the shorter version 35 | # eqN - equal up to N sub-version levels 36 | # neN - not equal up to N sub-version levels 37 | # 38 | # When the condition is true, shell commands ACTION-IF-TRUE are run, 39 | # otherwise shell commands ACTION-IF-FALSE are run. The environment 40 | # variable 'ax_compare_version' is always set to either 'true' or 'false' 41 | # as well. 42 | # 43 | # Examples: 44 | # 45 | # AX_COMPARE_VERSION([3.15.7],[lt],[3.15.8]) 46 | # AX_COMPARE_VERSION([3.15],[lt],[3.15.8]) 47 | # 48 | # would both be true. 49 | # 50 | # AX_COMPARE_VERSION([3.15.7],[eq],[3.15.8]) 51 | # AX_COMPARE_VERSION([3.15],[gt],[3.15.8]) 52 | # 53 | # would both be false. 54 | # 55 | # AX_COMPARE_VERSION([3.15.7],[eq2],[3.15.8]) 56 | # 57 | # would be true because it is only comparing two minor versions. 58 | # 59 | # AX_COMPARE_VERSION([3.15.7],[eq0],[3.15]) 60 | # 61 | # would be true because it is only comparing the lesser number of minor 62 | # versions of the two values. 63 | # 64 | # Note: The characters that separate the version numbers do not matter. An 65 | # empty string is the same as version 0. OP is evaluated by autoconf, not 66 | # configure, so must be a string, not a variable. 67 | # 68 | # The author would like to acknowledge Guido Draheim whose advice about 69 | # the m4_case and m4_ifvaln functions make this macro only include the 70 | # portions necessary to perform the specific comparison specified by the 71 | # OP argument in the final configure script. 72 | # 73 | # LICENSE 74 | # 75 | # Copyright (c) 2008 Tim Toolan 76 | # 77 | # Copying and distribution of this file, with or without modification, are 78 | # permitted in any medium without royalty provided the copyright notice 79 | # and this notice are preserved. This file is offered as-is, without any 80 | # warranty. 81 | 82 | #serial 13 83 | 84 | dnl ######################################################################### 85 | AC_DEFUN([AX_COMPARE_VERSION], [ 86 | AC_REQUIRE([AC_PROG_AWK]) 87 | 88 | # Used to indicate true or false condition 89 | ax_compare_version=false 90 | 91 | # Convert the two version strings to be compared into a format that 92 | # allows a simple string comparison. The end result is that a version 93 | # string of the form 1.12.5-r617 will be converted to the form 94 | # 0001001200050617. In other words, each number is zero padded to four 95 | # digits, and non digits are removed. 96 | AS_VAR_PUSHDEF([A],[ax_compare_version_A]) 97 | A=`echo "$1" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \ 98 | -e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \ 99 | -e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \ 100 | -e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \ 101 | -e 's/[[^0-9]]//g'` 102 | 103 | AS_VAR_PUSHDEF([B],[ax_compare_version_B]) 104 | B=`echo "$3" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \ 105 | -e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \ 106 | -e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \ 107 | -e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \ 108 | -e 's/[[^0-9]]//g'` 109 | 110 | dnl # In the case of le, ge, lt, and gt, the strings are sorted as necessary 111 | dnl # then the first line is used to determine if the condition is true. 112 | dnl # The sed right after the echo is to remove any indented white space. 113 | m4_case(m4_tolower($2), 114 | [lt],[ 115 | ax_compare_version=`echo "x$A 116 | x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/false/;s/x${B}/true/;1q"` 117 | ], 118 | [gt],[ 119 | ax_compare_version=`echo "x$A 120 | x$B" | sed 's/^ *//' | sort | sed "s/x${A}/false/;s/x${B}/true/;1q"` 121 | ], 122 | [le],[ 123 | ax_compare_version=`echo "x$A 124 | x$B" | sed 's/^ *//' | sort | sed "s/x${A}/true/;s/x${B}/false/;1q"` 125 | ], 126 | [ge],[ 127 | ax_compare_version=`echo "x$A 128 | x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/true/;s/x${B}/false/;1q"` 129 | ],[ 130 | dnl Split the operator from the subversion count if present. 131 | m4_bmatch(m4_substr($2,2), 132 | [0],[ 133 | # A count of zero means use the length of the shorter version. 134 | # Determine the number of characters in A and B. 135 | ax_compare_version_len_A=`echo "$A" | $AWK '{print(length)}'` 136 | ax_compare_version_len_B=`echo "$B" | $AWK '{print(length)}'` 137 | 138 | # Set A to no more than B's length and B to no more than A's length. 139 | A=`echo "$A" | sed "s/\(.\{$ax_compare_version_len_B\}\).*/\1/"` 140 | B=`echo "$B" | sed "s/\(.\{$ax_compare_version_len_A\}\).*/\1/"` 141 | ], 142 | [[0-9]+],[ 143 | # A count greater than zero means use only that many subversions 144 | A=`echo "$A" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"` 145 | B=`echo "$B" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"` 146 | ], 147 | [.+],[ 148 | AC_WARNING( 149 | [invalid OP numeric parameter: $2]) 150 | ],[]) 151 | 152 | # Pad zeros at end of numbers to make same length. 153 | ax_compare_version_tmp_A="$A`echo $B | sed 's/./0/g'`" 154 | B="$B`echo $A | sed 's/./0/g'`" 155 | A="$ax_compare_version_tmp_A" 156 | 157 | # Check for equality or inequality as necessary. 158 | m4_case(m4_tolower(m4_substr($2,0,2)), 159 | [eq],[ 160 | test "x$A" = "x$B" && ax_compare_version=true 161 | ], 162 | [ne],[ 163 | test "x$A" != "x$B" && ax_compare_version=true 164 | ],[ 165 | AC_WARNING([invalid OP parameter: $2]) 166 | ]) 167 | ]) 168 | 169 | AS_VAR_POPDEF([A])dnl 170 | AS_VAR_POPDEF([B])dnl 171 | 172 | dnl # Execute ACTION-IF-TRUE / ACTION-IF-FALSE. 173 | if test "$ax_compare_version" = "true" ; then 174 | m4_ifvaln([$4],[$4],[:])dnl 175 | m4_ifvaln([$5],[else $5])dnl 176 | fi 177 | ]) dnl AX_COMPARE_VERSION 178 | -------------------------------------------------------------------------------- /patricia.h: -------------------------------------------------------------------------------- 1 | #ifndef _PATRICIA_H 2 | #define _PATRICIA_H 3 | 4 | #define HAVE_IPV6 1 5 | 6 | /* typedef unsigned int u_int; */ 7 | typedef void (*void_fn_t)(); 8 | /* { from defs.h */ 9 | #define prefix_touchar(prefix) ((u_char *)&(prefix)->add.sin) 10 | #define MAXLINE 4096 11 | #define BIT_TEST(f, b) ((f) & (b)) 12 | /* } */ 13 | 14 | #define addroute make_and_lookup 15 | 16 | #include /* for u_* definitions (on FreeBSD 5) */ 17 | 18 | #include /* for EAFNOSUPPORT */ 19 | #ifndef EAFNOSUPPORT 20 | # defined EAFNOSUPPORT WSAEAFNOSUPPORT 21 | # include 22 | #else 23 | # include /* for struct in_addr */ 24 | #endif 25 | 26 | #include /* for AF_INET */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | typedef struct _prefix4_t { 34 | u_short family; /* AF_INET | AF_INET6 */ 35 | u_short bitlen; /* same as mask? */ 36 | int ref_count; /* reference count */ 37 | struct in_addr sin; 38 | } prefix4_t; 39 | 40 | typedef struct _prefix_t { 41 | u_short family; /* AF_INET | AF_INET6 */ 42 | u_short bitlen; /* same as mask? */ 43 | int ref_count; /* reference count */ 44 | union { 45 | struct in_addr sin; 46 | #ifdef HAVE_IPV6 47 | struct in6_addr sin6; 48 | #endif /* IPV6 */ 49 | } add; 50 | } prefix_t; 51 | 52 | 53 | typedef struct _patricia_node_t { 54 | u_int bit; /* flag if this node used */ 55 | prefix_t *prefix; /* who we are in patricia tree */ 56 | struct _patricia_node_t *l, *r; /* left and right children */ 57 | struct _patricia_node_t *parent;/* may be used */ 58 | void *data; /* pointer to data */ 59 | void *user1; /* pointer to usr data (ex. route flap info) */ 60 | // unsigned int children; 61 | } patricia_node_t; 62 | 63 | typedef struct _patricia_tree_t { 64 | patricia_node_t *head; 65 | u_int maxbits; /* for IP, 32 bit addresses */ 66 | int num_active_node; /* for debug purpose */ 67 | } patricia_tree_t; 68 | 69 | 70 | patricia_node_t *patricia_search_exact (patricia_tree_t *patricia, prefix_t *prefix); 71 | patricia_node_t *patricia_search_best (patricia_tree_t *patricia, prefix_t *prefix); 72 | patricia_node_t * patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix, 73 | int inclusive); 74 | patricia_node_t *patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix); 75 | void patricia_remove (patricia_tree_t *patricia, patricia_node_t *node); 76 | patricia_tree_t *New_Patricia (int maxbits); 77 | void Clear_Patricia (patricia_tree_t *patricia); 78 | void Destroy_Patricia (patricia_tree_t *patricia); 79 | void patricia_process (patricia_tree_t *patricia, void_fn_t func); 80 | const char *prefix_toa (prefix_t * prefix); 81 | patricia_node_t *try_search_best (patricia_tree_t *tree, char *string); 82 | patricia_node_t *try_search_exact (patricia_tree_t *tree, char *string); 83 | size_t patricia_walk_inorder(patricia_node_t *node); 84 | prefix_t *ascii2prefix (int family, const char *string); 85 | prefix_t *int2prefix (uint32_t addr); 86 | void Deref_Prefix(prefix_t *); 87 | 88 | #define PATRICIA_MAXBITS 128 89 | #define PATRICIA_NBIT(x) (0x80 >> ((x) & 0x7f)) 90 | #define PATRICIA_NBYTE(x) ((x) >> 3) 91 | 92 | #define PATRICIA_DATA_GET(node, type) (type *)((node)->data) 93 | #define PATRICIA_DATA_SET(node, value) ((node)->data = (void *)(value)) 94 | 95 | #define PATRICIA_WALK(Xhead, Xnode) \ 96 | do { \ 97 | patricia_node_t *Xstack[PATRICIA_MAXBITS+1]; \ 98 | patricia_node_t **Xsp = Xstack; \ 99 | patricia_node_t *Xrn = (Xhead); \ 100 | while ((Xnode = Xrn)) { \ 101 | if (Xnode->prefix) 102 | 103 | #define PATRICIA_WALK_ALL(Xhead, Xnode) \ 104 | do { \ 105 | patricia_node_t *Xstack[PATRICIA_MAXBITS+1]; \ 106 | patricia_node_t **Xsp = Xstack; \ 107 | patricia_node_t *Xrn = (Xhead); \ 108 | while ((Xnode = Xrn)) { \ 109 | if (1) 110 | 111 | #define PATRICIA_WALK_BREAK { \ 112 | if (Xsp != Xstack) { \ 113 | Xrn = *(--Xsp); \ 114 | } else { \ 115 | Xrn = (patricia_node_t *) 0; \ 116 | } \ 117 | continue; } 118 | 119 | #define PATRICIA_WALK_END \ 120 | if (Xrn->l) { \ 121 | if (Xrn->r) { \ 122 | *Xsp++ = Xrn->r; \ 123 | } \ 124 | Xrn = Xrn->l; \ 125 | } else if (Xrn->r) { \ 126 | Xrn = Xrn->r; \ 127 | } else if (Xsp != Xstack) { \ 128 | Xrn = *(--Xsp); \ 129 | } else { \ 130 | Xrn = (patricia_node_t *) 0; \ 131 | } \ 132 | } \ 133 | } while (0) 134 | 135 | class Patricia { 136 | public: 137 | Patricia(uint8_t size) { 138 | tree = New_Patricia(size); 139 | }; 140 | ~Patricia() { 141 | Destroy_Patricia(tree); 142 | }; 143 | template patricia_node_t *add_ref(const char *string, Type *val) { 144 | prefix_t *prefix = ascii2prefix(AF_INET, string); 145 | patricia_node_t *node = patricia_lookup(tree, prefix); 146 | if (node) { 147 | if (node->user1 == NULL) { 148 | node->user1 = val; 149 | } 150 | } 151 | Deref_Prefix(prefix); 152 | return (node); 153 | } 154 | template patricia_node_t *add(int family, const char *string, Type *val) { 155 | size_t size = sizeof(*val); 156 | prefix_t *prefix = ascii2prefix(family, string); 157 | patricia_node_t *node = patricia_lookup(tree, prefix); 158 | if (node) { 159 | /* only set data if node didn't already exist */ 160 | if (node->user1 == NULL) { 161 | node->user1 = calloc(1, size); 162 | memcpy(node->user1, val, size); 163 | } 164 | } 165 | Deref_Prefix(prefix); 166 | return (node); 167 | } 168 | patricia_node_t *add(const char *string, int val) { 169 | return (add(AF_INET, string, &val)); 170 | } 171 | patricia_node_t *add(int family, const char *string, int val) { 172 | return (add(family, string, &val)); 173 | } 174 | void *get(uint32_t addr, bool exact); 175 | void *get(uint32_t addr) { 176 | return (get(addr, false)); 177 | } 178 | void *get(struct in6_addr addr); 179 | void *get(int family, const char *string, bool exact); 180 | void *get(const char *string) { 181 | return (get(AF_INET, string, false)); 182 | } 183 | void *get(int family, const char *string) { 184 | return (get(family, string, false)); 185 | } 186 | void populate(int family, const char *filename); 187 | void populate(int family, const char *filename, bool block); 188 | void populateBlock(int family, const char *filename); 189 | void populate(const char *filename) { 190 | populate(AF_INET, filename); 191 | }; 192 | void populate6(const char *filename) { 193 | populate(AF_INET6, filename); 194 | }; 195 | void populateStatus(const char *filename); 196 | int matchingPrefix(uint32_t addr); 197 | int matchingPrefix(const char *string, int family); 198 | 199 | private: 200 | int parseBGPLine(char *, std::string *, uint32_t *, int *); 201 | int parsePrefix(int family, char *, std::string *); 202 | void *get(prefix_t *prefix, bool exact); 203 | int matchingPrefix(prefix_t *prefix); 204 | patricia_tree_t *tree; 205 | }; 206 | 207 | #endif /* _PATRICIA_H */ 208 | 209 | 210 | -------------------------------------------------------------------------------- /utils/yrp2warts/yarrpfile.hpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (c) 2016-2019 Justin P. Rohrer 3 | * All rights reserved. 4 | * 5 | * Program: $Id: yarrpfile.hpp $ 6 | * Description: Process Yarrp output 7 | * 8 | * Attribution: R. Beverly, "Yarrp'ing the Internet: Randomized High-Speed 9 | * Active Topology Discovery", Proceedings of the ACM SIGCOMM 10 | * Internet Measurement Conference, November, 2016 11 | ***************************************************************************/ 12 | 13 | #ifndef YARRPFILE_INCLUDED 14 | #define YARRPFILE_INCLUDED 15 | 16 | //#include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include "ipaddress.hpp" 25 | 26 | using namespace std; 27 | using namespace ip; 28 | 29 | // from scamper/trace/scamper_trace.h 30 | typedef enum {ICMP6 = 0x04, ICMP = 0x04, UDP6 = 0x05, UDP = 0x05, TCP6_SYN = 0x03, TCP_SYN = 0x03, TCP6_ACK = 0x06, TCP_ACK = 0x06} traceroute_t; 31 | 32 | // from yarrp/src/trace.h 33 | static vector traceroute_type = {ICMP6, ICMP, UDP6, UDP, TCP6_SYN, TCP_SYN, TCP6_ACK, TCP_ACK}; 34 | 35 | static unordered_map tracetype_names = { {"ICMP", ICMP}, {"ICMP6", ICMP6}, {"UDP", UDP}, {"UDP6", UDP6}, {"TCP_SYN", TCP_SYN}, {"TCP6_SYN", TCP6_SYN}, {"TCP_ACK", TCP_ACK}, {"TCP6_ACK", TCP6_ACK} }; 36 | 37 | 38 | struct yarrpRecord 39 | { 40 | ipaddress target; 41 | uint32_t sec; 42 | uint32_t usec; 43 | uint8_t typ; 44 | uint8_t code; 45 | uint8_t ttl; 46 | ipaddress hop; 47 | uint32_t rtt; 48 | uint16_t ipid; 49 | uint16_t psize; 50 | uint16_t rsize; 51 | uint8_t rttl; 52 | uint8_t rtos; 53 | uint64_t count; 54 | }; 55 | 56 | ostream& operator<< (ostream& os, const yarrpRecord& r) 57 | { 58 | return os << r.target << ", " << r.sec << ", " << r.usec << ", " << uint16_t(r.typ) << ", " << uint16_t(r.code) << ", " << uint16_t(r.ttl) << ", " << r.hop << ", " << r.rtt << ", " << r.ipid << ", " << r.psize << ", " << r.rsize << ", " << uint16_t(r.rttl) << ", " << uint16_t(r.rtos) << ", " << r.count; 59 | } 60 | istream& operator>> (istream &in, yarrpRecord& r) 61 | { 62 | uint16_t typ, code, ttl, rttl, rtos; 63 | in >> r.target >> r.sec >> r.usec >> typ >> code >> ttl >> r.hop >> r.rtt >> r.ipid >> r.psize >> r.rsize >> rttl >> rtos >> r.count; 64 | 65 | r.typ = typ; 66 | r.code = code; 67 | r.ttl = ttl; 68 | r.rttl = rttl; 69 | r.rtos = rtos; 70 | return in; 71 | } 72 | 73 | class yarrpFile 74 | { 75 | private: 76 | ifstream m_fh; 77 | istream *m_fhs; 78 | bool read_file; 79 | ipaddress m_source; 80 | bool m_usGranularity; 81 | uint8_t m_traceType; 82 | uint16_t m_maxTtl; 83 | uint16_t m_fillTtl; 84 | uint64_t m_fills; 85 | uint64_t m_pkts; 86 | string m_startTime; 87 | string m_endTime; 88 | uint8_t m_columns; 89 | bool readHeader(); 90 | bool readTrailer(); 91 | 92 | public: 93 | yarrpFile() : m_usGranularity(false), m_columns(0) {}; 94 | bool open(string fn); 95 | bool open(istream& input_stream); 96 | void close(); 97 | bool nextRecord(yarrpRecord &r); 98 | ipaddress getSource() const; 99 | uint8_t getType() const; 100 | uint16_t getMaxTtl() const; 101 | }; 102 | 103 | bool yarrpFile::open(string fn) 104 | { 105 | cout << "Opening Yarrp file: " << fn << endl; 106 | m_fh.open(fn, ifstream::in); 107 | m_fhs = &m_fh; 108 | read_file = true; 109 | return readHeader(); 110 | } 111 | 112 | bool yarrpFile::open(istream& input_stream) 113 | { 114 | cout << "Opening input stream" << endl; 115 | ios_base::sync_with_stdio(false); 116 | m_fhs = &input_stream; 117 | read_file = false; 118 | return readHeader(); 119 | } 120 | 121 | void yarrpFile::close() 122 | { 123 | if (m_fh.is_open()) { 124 | m_fh.close(); 125 | } 126 | } 127 | 128 | bool yarrpFile::readHeader() 129 | { 130 | //cout << "Reading Yarrp header" << endl; 131 | if (!m_fhs->good()) { 132 | cerr << "Input not good" << endl; 133 | return false; 134 | } 135 | string line; 136 | string hash; 137 | string param; 138 | int headerlines = 0; 139 | while (m_fhs->peek() == '#') { 140 | getline(*m_fhs, line); 141 | //cout << line << endl; 142 | replace(line.begin(), line.end(), ',', ' '); 143 | istringstream iss(line); 144 | iss >> hash >> param; 145 | if (param == "yarrp") { 146 | string ver; 147 | iss >> ver; 148 | if (ver == "v0.5") { 149 | cerr << "yrp2warts only works with version 0.6 or newer .yrp files!" << endl; 150 | return false; 151 | } 152 | } 153 | if (param == "Start:") { 154 | string dow, dom, month, year, tod, tz; 155 | //iss >> dow >> month >> dom >> tod >> year; 156 | iss >> dow >> dom >> month >> year >> tod >> tz; 157 | m_startTime = dow + " " + dom + " " + month + " " + year + " " + tod + " " + tz; 158 | //cout << m_startTime << endl; 159 | } 160 | if (param == "SourceIP:") { 161 | iss >> m_source; 162 | //cout << m_source << endl; 163 | } 164 | if (param == "Trace_Type:") { 165 | string type_name; 166 | iss >> type_name; 167 | m_traceType = tracetype_names[type_name]; 168 | //cout << int(m_traceType) << endl; 169 | } 170 | //if (param == "Rate:") {} 171 | if (param == "Max_TTL:") { 172 | iss >> m_maxTtl; 173 | //cout << m_maxTtl << endl; 174 | } 175 | if (param == "Fill_Mode:") { 176 | iss >> m_fillTtl; 177 | //cout << m_maxTtl << " " << m_fillTtl << endl; 178 | } 179 | if (param == "RTT_Granularity:") { 180 | string trash, units; 181 | iss >> trash >> units; 182 | if (units == "us") { 183 | m_usGranularity = true; 184 | } 185 | //cout << m_usGranularity << endl; 186 | } 187 | if (param == "Output_Fields:") { 188 | string trash; 189 | m_columns = 0; 190 | while (iss >> trash) { 191 | m_columns++; 192 | } 193 | //cout << int(m_columns) << endl; 194 | } 195 | headerlines++; 196 | } 197 | if (headerlines > 0) { 198 | return true; 199 | } 200 | return false; 201 | } 202 | 203 | bool yarrpFile::readTrailer() 204 | { 205 | //cout << "Reading Yarrp trailer" << endl; 206 | if (!m_fh.good()) { 207 | return false; 208 | } 209 | string line; 210 | string hash; 211 | string param; 212 | int trailerlines = 0; 213 | while (m_fhs->peek() == '#') { 214 | getline(*m_fhs, line); 215 | //cout << line << endl; 216 | istringstream iss(line); 217 | iss >> hash >> param; 218 | if (param == "End:") { 219 | string dow, dom, month, year, tod, tz; 220 | iss >> dow >> dom >> month >> year >> tod >> tz; 221 | m_endTime = dow + " " + dom + " " + month + " " + year + " " + tod + " " + tz; 222 | //cout << m_endTime << endl; 223 | } 224 | if (param == "Fills:") { 225 | iss >> m_fills; 226 | //cout << m_fills << endl; 227 | } 228 | if (param == "Pkts:") { 229 | iss >> m_pkts; 230 | //cout << m_pkts << endl; 231 | } 232 | trailerlines++; 233 | } 234 | if (trailerlines > 0) { 235 | return true; 236 | } 237 | return false; 238 | } 239 | 240 | bool yarrpFile::nextRecord(yarrpRecord &r) 241 | { 242 | string line; 243 | if (read_file) { 244 | if (!m_fh.good()) { 245 | return false; 246 | } 247 | if (m_fh.peek() == '#') { 248 | readTrailer(); 249 | return false; 250 | } 251 | getline(m_fh, line); 252 | } 253 | else { 254 | if (!m_fhs->good()) { 255 | return false; 256 | } 257 | if (m_fhs->peek() == '#') { 258 | readTrailer(); 259 | return false; 260 | } 261 | getline(*m_fhs, line); 262 | } 263 | //replace(line.begin(), line.end(), ',', ' '); 264 | istringstream iss(line); 265 | iss >> r; 266 | return true; 267 | } 268 | 269 | ipaddress yarrpFile::getSource() const 270 | { 271 | return m_source; 272 | } 273 | 274 | uint8_t yarrpFile::getType() const 275 | { 276 | return m_traceType; 277 | } 278 | 279 | uint16_t yarrpFile::getMaxTtl() const 280 | { 281 | return m_maxTtl; 282 | } 283 | 284 | #endif -------------------------------------------------------------------------------- /utils/yrp2warts/ipaddress.hpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (c) 2016-2019 Justin P. Rohrer 3 | * All rights reserved. 4 | * 5 | * Program: $Id: ipaddress.hpp $ 6 | * Description: Class to store an IPv4 or IPv6 address 7 | * 8 | ***************************************************************************/ 9 | 10 | #ifndef IPADDRESS_INCLUDED 11 | #define IPADDRESS_INCLUDED 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | //using namespace std; 19 | namespace ip 20 | { 21 | 22 | /*struct free_deleter 23 | { 24 | template 25 | void operator()(T *p) const { 26 | //free(const_cast*>(p)); 27 | } 28 | };*/ 29 | 30 | class ipaddress 31 | { 32 | private: 33 | //unique_ptr m_v4addr; 34 | //unique_ptr m_v6addr; 35 | //shared_ptr m_v4addr; 36 | std::shared_ptr m_v4addr; 37 | //shared_ptr m_v4addr; 38 | //shared_ptr m_v6addr; 39 | std::shared_ptr > m_v6addr; 40 | 41 | public: 42 | //ipaddress() : m_v4addr(NULL), m_v6addr(NULL) {}; 43 | ipaddress() {}; 44 | //ipaddress(string addr) : m_v4addr(NULL), m_v6addr(NULL) 45 | ipaddress(std::string addr) 46 | { 47 | set(addr); 48 | } 49 | int8_t set(std::string addr) 50 | { 51 | if (addr.length() > 15 || addr.find(':') != std::string::npos) { 52 | //m_v6addr = (in6_addr *) malloc(sizeof(in6_addr)); 53 | //m_v6addr.reset((in6_addr *) malloc(sizeof(in6_addr))); 54 | //m_v6addr = make_unique(); 55 | //m_v6addr = unique_ptr((in6_addr *) malloc(sizeof(in6_addr)), free_deleter()); 56 | //m_v6addr = unique_ptr(new in6_addr, free_deleter()); 57 | //m_v6addr = shared_ptr((in6_addr *) malloc(sizeof(in6_addr)), free); 58 | //m_v6addr = make_shared(); 59 | m_v6addr = std::make_shared >(); 60 | in6_addr temp6_addr; 61 | int result = inet_pton(AF_INET6, addr.c_str(), &temp6_addr); 62 | //cout << "set: "; 63 | for (int i = 0; i<16; i++) { 64 | m_v6addr->at(i) = temp6_addr.s6_addr[i]; 65 | //cout << int(m_v6addr->at(i)); 66 | } 67 | //cout << endl; 68 | //free(temp6_addr); 69 | return result; 70 | } 71 | //m_v4addr = (in_addr *) malloc(sizeof(in_addr)); 72 | //m_v4addr.reset((in_addr *) malloc(sizeof(in_addr))); 73 | //m_v4addr = make_unique(); 74 | //m_v4addr = unique_ptr((in_addr *) malloc(sizeof(in_addr)), free_deleter()); 75 | //m_v4addr = unique_ptr(new in_addr, free_deleter()); 76 | //m_v4addr = shared_ptr((in_addr *) malloc(sizeof(in_addr)), free); 77 | //m_v4addr = make_shared(); 78 | in_addr temp_addr; 79 | int result = inet_pton(AF_INET, addr.c_str(), &temp_addr); 80 | m_v4addr = std::make_shared(temp_addr.s_addr); 81 | return result; 82 | } 83 | uint8_t version() const 84 | { 85 | if (m_v4addr) { 86 | return 4; 87 | } 88 | if (m_v6addr) { 89 | return 6; 90 | } 91 | return 0; 92 | } 93 | std::string tostr() const 94 | { 95 | if (m_v4addr) { 96 | in_addr temp_addr; 97 | temp_addr.s_addr = *m_v4addr; 98 | char addrstring[INET_ADDRSTRLEN]; 99 | return std::string(inet_ntop(AF_INET, &temp_addr, addrstring, INET_ADDRSTRLEN)); 100 | } 101 | if (m_v6addr) { 102 | in6_addr temp6_addr; 103 | //cout << "get: "; 104 | for (int i = 0; i<16; i++) { 105 | temp6_addr.s6_addr[i] = m_v6addr->at(i); 106 | //cout << int(temp6_addr.s6_addr[i]); 107 | } 108 | //cout << endl; 109 | char addr6string[INET6_ADDRSTRLEN]; 110 | return std::string(inet_ntop(AF_INET6, &temp6_addr, addr6string, INET6_ADDRSTRLEN)); 111 | } 112 | return std::string(); 113 | } 114 | std::size_t hash() const 115 | { 116 | if (m_v4addr) { 117 | return std::hash()(*m_v4addr); 118 | } 119 | if (m_v6addr) { 120 | //return std::hash >()(*m_v6addr); 121 | uint64_t mangle_h = (*m_v6addr)[8]; 122 | uint64_t mangle_l = (*m_v6addr)[0]; 123 | for (int i=1; i<8; i++) { 124 | mangle_h <<= 8; 125 | mangle_h ^= (*m_v6addr)[i+8]; 126 | mangle_l <<= 8; 127 | mangle_l ^= (*m_v6addr)[i]; 128 | } 129 | return std::hash()(mangle_h ^ mangle_l); 130 | } 131 | return 0; 132 | } 133 | /*template 134 | const shared_ptr* get() const 135 | { 136 | if (m_v4addr) { 137 | return m_v4addr; 138 | } 139 | if (m_v6addr) { 140 | return m_v6addr; 141 | } 142 | cerr << "No addr set" << endl; 143 | exit(1); 144 | }*/ 145 | std::shared_ptr get4() const 146 | { 147 | if (m_v4addr) { 148 | return m_v4addr; 149 | } 150 | std::cerr << "No v4 addr set" << std::endl; 151 | exit(1); 152 | } 153 | std::shared_ptr > get6() const 154 | { 155 | if (m_v6addr) { 156 | return m_v6addr; 157 | } 158 | std::cerr << "No v6 addr set" << std::endl; 159 | exit(1); 160 | } 161 | /* ipaddress& operator= (const ipaddress &ip) 162 | { 163 | if (ip.m_v4addr) { 164 | if (m_v6addr) { 165 | m_v6addr.release(); 166 | } 167 | m_v4addr = unique_ptr((in_addr *) malloc(sizeof(in_addr)), free_deleter()); 168 | m_v4addr->s_addr = ip.m_v4addr->s_addr; 169 | } 170 | if (ip.m_v6addr) { 171 | if (m_v4addr) { 172 | m_v4addr.release(); 173 | } 174 | m_v6addr = unique_ptr((in6_addr *) malloc(sizeof(in6_addr)), free_deleter()); 175 | m_v6addr->s6_addr = ip.m_v6addr->s6_addr; 176 | } 177 | return *this; 178 | } */ 179 | //friend ostream& operator<< (ostream& os, const ipaddress& ip); 180 | //friend istream& operator>> (istream &in, ipaddress &ip); 181 | friend bool operator> (const ipaddress &ip1, const ipaddress &ip2); 182 | friend bool operator< (const ipaddress &ip1, const ipaddress &ip2); 183 | bool operator== (const ipaddress &other) const 184 | { 185 | if (m_v4addr && other.m_v4addr) { 186 | return *m_v4addr == *other.m_v4addr; 187 | } 188 | if (m_v6addr && other.m_v6addr) { 189 | return *m_v6addr == *other.m_v6addr; 190 | } 191 | return false; 192 | } 193 | }; 194 | 195 | std::ostream& operator<< (std::ostream& os, const ipaddress& ip) 196 | { 197 | return os << ip.tostr(); 198 | } 199 | 200 | std::istream& operator>> (std::istream &in, ipaddress &ip) 201 | { 202 | std::string addr; 203 | in >> addr; 204 | ip.set(addr); 205 | return in; 206 | } 207 | 208 | bool operator> (const ipaddress &ip1, const ipaddress &ip2) 209 | { 210 | if (ip1.m_v4addr && ip2.m_v4addr) { 211 | //cout << "Compare> v4" << endl; 212 | return *ip1.m_v4addr > *ip2.m_v4addr; 213 | } 214 | if (ip1.m_v6addr && ip2.m_v6addr) { 215 | //cout << "Compare> v6" << endl; 216 | //return ip1.m_v6addr->s6_addr > ip2.m_v6addr->s6_addr; 217 | return *ip1.m_v6addr > *ip2.m_v6addr; 218 | } 219 | return false; 220 | } 221 | 222 | bool operator< (const ipaddress &ip1, const ipaddress &ip2) 223 | { 224 | if (ip1.m_v4addr && ip2.m_v4addr) { 225 | //cout << "Compare< v4" << endl; 226 | //cout << *ip2.m_v4addr << endl; 227 | //cout << *ip1.m_v4addr << endl; 228 | return *ip1.m_v4addr < *ip2.m_v4addr; 229 | } 230 | if (ip1.m_v6addr && ip2.m_v6addr) { 231 | //cout << "Compare< v6" << endl; 232 | //return ip1.m_v6addr->s6_addr < ip2.m_v6addr->s6_addr; 233 | return *ip1.m_v6addr < *ip2.m_v6addr; 234 | } 235 | return false; 236 | } 237 | } // End namespace ip 238 | 239 | namespace std { 240 | template <> 241 | struct hash 242 | { 243 | std::size_t operator()(const ip::ipaddress& ip) const 244 | { 245 | using std::size_t; 246 | using std::hash; 247 | using std::string; 248 | 249 | //return (hash()(ip.tostr())); 250 | return ip.hash(); 251 | } 252 | }; 253 | } // End namespace std 254 | 255 | #endif 256 | -------------------------------------------------------------------------------- /libcperm/ciphers/speck.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, Moritz Bitsch 3 | 4 | Permission to use, copy, modify, and/or distribute this software for any 5 | purpose with or without fee is hereby granted, provided that the above 6 | copyright notice and this permission notice appear in all copies. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | #include "speck.h" 17 | 18 | #if WORDSIZE == 24 19 | // rotates for word size n=24 bits 20 | #define ROR(x, r) ((x >> r) | (x << (24 - r))&MASK24)&MASK24 21 | #define ROL(x, r) ((x << r) | (x >> (24 - r))&MASK24)&MASK24 22 | #elif WORDSIZE == 48 23 | #define ROR(x, r) ((x >> r) | (x << (48 - r))&MASK48)&MASK48 24 | #define ROL(x, r) ((x << r) | (x >> (48 - r))&MASK48)&MASK48 25 | #else 26 | #define ROR(x, r) ((x >> r) | (x << ((sizeof(SPECK_TYPE) * 8) - r))) 27 | #define ROL(x, r) ((x << r) | (x >> ((sizeof(SPECK_TYPE) * 8) - r))) 28 | #endif 29 | 30 | #ifdef SPECK_32_64 31 | #define R(x, y, k) (x = ROR(x, 7), x += y, x ^= k, y = ROL(y, 2), y ^= x) 32 | #define RR(x, y, k) (y ^= x, y = ROR(y, 2), x ^= k, x -= y, x = ROL(x, 7)) 33 | #else 34 | #if WORDSIZE == 24 35 | #define R(x, y, k) (x = ROR(x, 8), x = (x + y)&MASK24, x ^= k, y = ROL(y, 3), y ^= x) 36 | #define RR(x, y, k) (y ^= x, y = ROR(y, 3), x ^= k, x = (x - y)&MASK24, x = ROL(x, 8)) 37 | #elif WORDSIZE == 48 38 | #define R(x, y, k) (x = ROR(x, 8), x = (x + y)&MASK48, x ^= k, y = ROL(y, 3), y ^= x) 39 | #define RR(x, y, k) (y ^= x, y = ROR(y, 3), x ^= k, x = (x - y)&MASK48, x = ROL(x, 8)) 40 | #else 41 | #define R(x, y, k) (x = ROR(x, 8), x += y, x ^= k, y = ROL(y, 3), y ^= x) 42 | #define RR(x, y, k) (y ^= x, y = ROR(y, 3), x ^= k, x -= y, x = ROL(x, 8)) 43 | #endif 44 | #endif 45 | 46 | struct speck_data { 47 | #ifdef SPECK_32_64 48 | uint16_t key[4]; 49 | SPECK_TYPE exp[SPECK_ROUNDS]; 50 | #endif 51 | }; 52 | 53 | int perm_speck_create(struct cperm_t *pt) { 54 | struct speck_data *d; 55 | 56 | if(pt->key_len != 8) { 57 | return PERM_ERROR_BAD_KEY_LENGTH; 58 | } 59 | 60 | d = malloc(sizeof(*d)); 61 | memcpy(&d->key, pt->key, pt->key_len); 62 | speck_expand(d->key, d->exp); 63 | 64 | pt->cipher_data = d; 65 | 66 | return 0; 67 | } 68 | 69 | int perm_speck_destroy(struct cperm_t* pt) { 70 | free(pt->cipher_data); 71 | return 0; 72 | } 73 | 74 | int perm_speck_enc(struct cperm_t* perm, uint64_t pt, uint64_t* ct) { 75 | struct speck_data* d = perm->cipher_data; 76 | 77 | SPECK_TYPE *plain = (SPECK_TYPE *) &pt; 78 | SPECK_TYPE *buffer = (SPECK_TYPE *) ct; 79 | 80 | speck_encrypt(plain, buffer, d->exp); 81 | return 0; 82 | } 83 | 84 | int perm_speck_dec(struct cperm_t* perm, uint64_t ct, uint64_t* pt) { 85 | struct speck_data* d = perm->cipher_data; 86 | 87 | SPECK_TYPE *enc = (SPECK_TYPE *) &ct; 88 | SPECK_TYPE *buffer = (SPECK_TYPE *) pt; 89 | 90 | speck_decrypt(enc, buffer, d->exp); 91 | return 0; 92 | } 93 | 94 | void speck_expand(SPECK_TYPE const K[static SPECK_KEY_LEN], SPECK_TYPE S[static SPECK_ROUNDS]) 95 | { 96 | SPECK_TYPE i, b = K[0]; 97 | SPECK_TYPE a[SPECK_KEY_LEN - 1]; 98 | 99 | for (i = 0; i < (SPECK_KEY_LEN - 1); i++) 100 | { 101 | a[i] = K[i + 1]; 102 | } 103 | S[0] = b; 104 | for (i = 0; i < SPECK_ROUNDS - 1; i++) { 105 | R(a[i % (SPECK_KEY_LEN - 1)], b, i); 106 | S[i + 1] = b; 107 | } 108 | } 109 | 110 | void speck_encrypt(SPECK_TYPE const pt[static 2], SPECK_TYPE ct[static 2], SPECK_TYPE const K[static SPECK_ROUNDS]) 111 | { 112 | SPECK_TYPE i; 113 | ct[0]=pt[0]; ct[1]=pt[1]; 114 | 115 | for(i = 0; i < SPECK_ROUNDS; i++){ 116 | R(ct[1], ct[0], K[i]); 117 | } 118 | } 119 | 120 | void speck_decrypt(SPECK_TYPE const ct[static 2], SPECK_TYPE pt[static 2], SPECK_TYPE const K[static SPECK_ROUNDS]) 121 | { 122 | SPECK_TYPE i; 123 | pt[0]=ct[0]; pt[1]=ct[1]; 124 | 125 | for(i = 0; i < SPECK_ROUNDS; i++){ 126 | RR(pt[1], pt[0], K[(SPECK_ROUNDS - 1) - i]); 127 | } 128 | } 129 | 130 | void speck_encrypt_combined(SPECK_TYPE const pt[static 2], SPECK_TYPE ct[static 2], SPECK_TYPE const K[static SPECK_KEY_LEN]) 131 | { 132 | SPECK_TYPE i, b = K[0]; 133 | SPECK_TYPE a[SPECK_KEY_LEN - 1]; 134 | ct[0]=pt[0]; ct[1]=pt[1]; 135 | 136 | for (i = 0; i < (SPECK_KEY_LEN - 1); i++) 137 | { 138 | a[i] = K[i + 1]; 139 | } 140 | 141 | R(ct[1], ct[0], b); 142 | for(i = 0; i < SPECK_ROUNDS - 1; i++){ 143 | R(a[i % (SPECK_KEY_LEN - 1)], b, i); 144 | R(ct[1], ct[0], b); 145 | } 146 | } 147 | 148 | void speck_decrypt_combined(SPECK_TYPE const ct[static 2], SPECK_TYPE pt[static 2], SPECK_TYPE const K[static SPECK_KEY_LEN]) 149 | { 150 | int i; 151 | SPECK_TYPE b = K[0]; 152 | SPECK_TYPE a[SPECK_KEY_LEN - 1]; 153 | pt[0]=ct[0]; pt[1]=ct[1]; 154 | 155 | for (i = 0; i < (SPECK_KEY_LEN - 1); i++) 156 | { 157 | a[i] = K[i + 1]; 158 | } 159 | 160 | for (i = 0; i < SPECK_ROUNDS - 1; i++) 161 | { 162 | R(a[i % (SPECK_KEY_LEN - 1)], b, i); 163 | } 164 | 165 | for(i = 0; i < SPECK_ROUNDS; i++){ 166 | RR(pt[1], pt[0], b); 167 | RR(a[((SPECK_ROUNDS - 2) - i) % (SPECK_KEY_LEN - 1)], b, ((SPECK_ROUNDS - 2) - i)); 168 | } 169 | } 170 | 171 | #ifdef TEST 172 | 173 | #include 174 | #include 175 | 176 | int main(int argc, char** argv) 177 | { 178 | #ifdef SPECK_32_64 179 | uint16_t key[4] = {0x0100, 0x0908, 0x1110, 0x1918}; 180 | uint16_t plain[2] = {0x694c, 0x6574}; 181 | uint16_t enc[2] = {0x42f2, 0xa868}; 182 | #endif 183 | 184 | #ifdef SPECK_48_72 185 | uint32_t key[3] = {0x020100, 0x0a0908, 0x121110}; 186 | uint32_t plain[2] = {0x6c6172, 0x20796c}; 187 | uint32_t enc[2] = {0x385adc, 0xc049a5}; 188 | #endif 189 | 190 | #ifdef SPECK_48_96 191 | uint32_t key[4] = {0x020100, 0x0a0908, 0x121110, 0x1a1918}; 192 | uint32_t plain[2] = {0x696874, 0x6d2073}; 193 | uint32_t enc[2] = {0xb6445d, 0x735e10}; 194 | #endif 195 | 196 | #ifdef SPECK_64_128 197 | uint32_t key[4] = {0x03020100, 0x0b0a0908, 0x13121110, 0x1b1a1918}; 198 | uint32_t plain[2] = {0x7475432d, 0x3b726574}; 199 | uint32_t enc[2] = {0x454e028b, 0x8c6fa548}; 200 | #endif 201 | 202 | #ifdef SPECK_96_96 203 | uint64_t key[2] = {0x050403020100, 0x0d0c0b0a0908}; 204 | uint64_t plain[2] = {0x656761737520, 0x65776f68202c}; 205 | uint64_t enc[2] = {0x62bdde8f79aa, 0x9e4d09ab7178}; 206 | #endif 207 | 208 | #ifdef SPECK_96_144 209 | uint64_t key[3] = {0x050403020100, 0x0d0c0b0a0908, 0x151413121110}; 210 | uint64_t plain[2] = {0x69202c726576, 0x656d6974206e}; 211 | uint64_t enc[2] = {0x7ae440252ee6, 0x2bf31072228a}; 212 | #endif 213 | 214 | #ifdef SPECK_128_256 215 | uint64_t key[4] = {0x0706050403020100, 0x0f0e0d0c0b0a0908, 0x1716151413121110, 0x1f1e1d1c1b1a1918}; 216 | uint64_t plain[2] = {0x202e72656e6f6f70, 0x65736f6874206e49}; 217 | uint64_t enc[2] = {0x4eeeb48d9c188f43, 0x4109010405c0f53e}; 218 | #endif 219 | 220 | SPECK_TYPE buffer[2] = {0}; 221 | SPECK_TYPE exp[SPECK_ROUNDS]; 222 | 223 | speck_expand(key, exp); 224 | 225 | #ifdef TEST_COMBINED 226 | speck_encrypt_combined(plain, buffer, key); 227 | #else 228 | speck_encrypt(plain, buffer, exp); 229 | #endif 230 | if (memcmp(buffer, enc, sizeof(enc))) { 231 | printf("encryption failed\n"); 232 | return 1; 233 | } 234 | #ifdef TEST_COMBINED 235 | speck_decrypt_combined(enc, buffer, key); 236 | #else 237 | speck_decrypt(enc, buffer, exp); 238 | #endif 239 | if (memcmp(buffer, plain, sizeof(enc))) { 240 | printf("decryption failed\n"); 241 | return 1; 242 | } 243 | printf("OK\n"); 244 | return 0; 245 | } 246 | 247 | #endif 248 | -------------------------------------------------------------------------------- /utils/yrp2warts.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2016-2018, Robert Beverly 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 are met: 8 | # * Redistributions of source code must retain the above copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # * Neither the name of the nor the 14 | # names of its contributors may be used to endorse or promote products 15 | # derived from this software without specific prior written permission. 16 | # 17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AN 18 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | # DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 21 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | # 28 | # Program: $Id: yrp2warts.py $ 29 | # Author: Robert Beverly 30 | # Description: Convert yarrp output to binary warts 31 | # 32 | import struct 33 | import operator 34 | import socket 35 | import math 36 | import argparse 37 | import sys 38 | import time 39 | from datetime import datetime 40 | from yarrpfile import Yarrp 41 | try: 42 | from sc_warts_writer import WartsWriter, WartsTrace 43 | except: 44 | print "Requires sc_warts_writer.py from https://github.com/cmand/scamper/" 45 | sys.exit(-1) 46 | 47 | try: 48 | import networkx as nx 49 | except: 50 | pass 51 | 52 | neighborhood = dict() 53 | 54 | def yarrp_proc(yarrpfile, traces, timestamps, subnet=None): 55 | # if we're converting a subset of the targets within the yrp trace 56 | (net, mask) = (None, None) 57 | (t_min, t_max) = (-1, -1) 58 | if (subnet): 59 | (s,mask) = subnet.split('/') 60 | mask = 2**int(mask) - 1 61 | net = dottedQuadToNum(s) 62 | 63 | yarrp = Yarrp(yarrpfile) 64 | while True: 65 | result = yarrp.next() 66 | if not result: break 67 | if not inNet(result['target'], net, mask): 68 | continue 69 | if result['target'] not in traces: 70 | traces[result['target']] = dict() 71 | # encode icmp type and code 72 | icmp_type_code = (result['typ'] << 8) + result['code'] 73 | traces[result['target']][int(result['ttl'])] = {'addr' : result['hop'], 'rtt' : result['rtt'], 74 | 'ipid' : result['ipid'], 'probesize' : result['psize'], 75 | 'replysize' : result['rsize'], 'probettl' : result['ttl'], 76 | 'replyttl' : result['rttl'], 'tos' : result['rtos'], 77 | 'icmp' : icmp_type_code, 'hopflags' : 0x10} 78 | # hopflags (SCAMPER_TRACE_HOP_FLAG_REPLY_TTL) 79 | timestamps[result['target']] = result['sec'] + (result['usec']/1000000.0) 80 | if t_min <= 0: t_min = timestamps[result['target']] 81 | if t_max <= 0: t_max = timestamps[result['target']] 82 | if timestamps[result['target']] < t_min: t_min = timestamps[result['target']] 83 | if timestamps[result['target']] > t_max: t_max = timestamps[result['target']] 84 | return (yarrp.vantage_point, yarrp.tracetype, yarrp.maxttl, t_min, t_max) 85 | 86 | 87 | # make_hops function that takes the networkx neighborhood graph to fill 88 | # in missing hops of the neighborhood 89 | def make_hops_nbr(hops, G): 90 | maxttl = max(hops) 91 | minttl = min(hops) 92 | path = None 93 | first_nbr_hop = None 94 | if G.has_node(hops[minttl][2]): 95 | first_nbr_hop = hops[minttl][2] 96 | print "Found path to TTL=min node." 97 | if 8 in hops: 98 | if G.has_node(hops[8][2]): 99 | first_nbr_hop = hops[8][2] 100 | print "Found path to TTL=8 node." 101 | 102 | if first_nbr_hop: 103 | print "computing shortest path to:", first_nbr_hop 104 | try: 105 | path = nx.shortest_path(G, source='src', target=first_nbr_hop) 106 | print "got path:", path 107 | except nx.NetworkXNoPath, e: 108 | print e 109 | return (path, maxttl) 110 | 111 | def dottedQuadToNum(ip): 112 | "convert decimal dotted quad string to long integer" 113 | return struct.unpack('I',socket.inet_aton(ip))[0] 114 | 115 | def inNet(ip, subnet, mask): 116 | if not subnet: 117 | return True 118 | nip = dottedQuadToNum(ip) 119 | if (nip & mask == subnet): 120 | return True 121 | else: 122 | return False 123 | 124 | def construct_nbrhood(inyrp): 125 | #import matplotlib.pyplot as plt 126 | G = nx.Graph() 127 | traces = dict() 128 | timestamps = dict() 129 | yarrp_proc(inyrp, traces, timestamps) 130 | for target in traces: 131 | #print "Target:", target 132 | hops = traces[target] 133 | (last_hop, last_ttl) = ('src', 0) 134 | for ttl in sorted(hops): 135 | #print "\t", ttl, hops[ttl]['addr'] 136 | if hop not in neighborhood: 137 | neighborhood[hop] = hops[ttl] 138 | G.add_node(hop) 139 | if last_ttl == ttl - 1: 140 | G.add_edge(last_hop, hop) 141 | (last_hop, last_ttl) = (hop, ttl) 142 | return G 143 | #nx.draw(G, with_labels=True) 144 | #plt.savefig("go.pdf") 145 | 146 | def main(): 147 | parser = argparse.ArgumentParser() 148 | parser.add_argument("-i", "--input", required=True, help="input yarrp file") 149 | parser.add_argument("-o", "--output", required=True, help="output warts file") 150 | parser.add_argument("-s", "--subnet", help="subnets to convert") 151 | parser.add_argument("-n", "--neighborhood", help="neighborhood yarrp file") 152 | args = parser.parse_args() 153 | 154 | if args.neighborhood: 155 | print "Reconstructing neighborhood" 156 | G = construct_nbrhood(args.neighborhood) 157 | 158 | # read and collect yarrp results into: 159 | # - traces[target][ttl] = hop_vals 160 | traces = dict() 161 | timestamps = dict() 162 | (vantage_point, tracetype, maxttl, t_min, t_max) = yarrp_proc(args.input, traces, timestamps, args.subnet) 163 | 164 | # open warts output 165 | w = WartsWriter(args.output) 166 | w.write_list(1, 1, 'yarrp') 167 | w.write_cycle(1, 1, 1, int(t_min)) 168 | processed = 0 169 | print ">>", datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S') 170 | tr = WartsTrace() 171 | 172 | # write each collected trace 173 | for target in traces: 174 | hops = traces[target] 175 | probehop = len(hops) if len(hops) > maxttl else maxttl 176 | if max(hops) > probehop: probehop = max(hops) 177 | probehop = max(hops) if max(hops) > probehop else probehop 178 | tr.add({'listid' : 1, 'srcport' : 1234, 'dstport' : 80, 179 | 'srcaddr' : vantage_point, 'dstaddr' : target, 180 | 'timeval' : timestamps[target], 'attempts' : 1, 181 | 'tracetyp' : tracetype, 'probehop' : probehop, 182 | 'probesent' : maxttl, 'firsttl' : 1}) 183 | 184 | if not args.neighborhood: 185 | for ttl in sorted(hops): 186 | tr.add_reply(hops[ttl]) 187 | else: 188 | (path, maxttl) = make_hops_nbr(hops, G) 189 | for ttl in range(1,maxttl+1): 190 | if ttl in hops: 191 | tr.add_reply(hops[ttl]) 192 | elif path: 193 | if ttl < len(path): 194 | hop = path[ttl] 195 | else: 196 | continue 197 | w.write_object(tr) 198 | processed+=1 199 | 200 | # finish 201 | w.write_cycle_stop(1, int(t_max)) 202 | print ">> Processed: %d targets" % processed 203 | print ">>", datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S') 204 | 205 | if __name__ == "__main__": 206 | main() 207 | -------------------------------------------------------------------------------- /trace6.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | Program: $Id: trace.cpp 39 2015-12-30 20:28:36Z rbeverly $ 3 | Date: $Date: 2015-12-30 12:28:36 -0800 (Wed, 30 Dec 2015) $ 4 | Description: traceroute class 5 | ****************************************************************************/ 6 | #include "yarrp.h" 7 | 8 | Traceroute6::Traceroute6(YarrpConfig *_config, Stats *_stats) : Traceroute(_config, _stats) { 9 | if (config->testing) return; 10 | memset(&source6, 0, sizeof(struct sockaddr_in6)); 11 | if (config->probesrc) { 12 | source6.sin6_family = AF_INET6; 13 | if (inet_pton(AF_INET6, config->probesrc, &source6.sin6_addr) != 1) 14 | fatal("** Bad source address."); 15 | } else { 16 | infer_my_ip6(&source6); 17 | } 18 | inet_ntop(AF_INET6, &source6.sin6_addr, addrstr, INET6_ADDRSTRLEN); 19 | config->set("SourceIP", addrstr, true); 20 | #ifdef _LINUX 21 | sndsock = raw_sock6(&source6); 22 | #else 23 | /* Init BPF socket */ 24 | sndsock = bpfget(); 25 | if (sndsock < 0) fatal("bpf open error\n"); 26 | struct ifreq bound_if; 27 | strcpy(bound_if.ifr_name, config->int_name); 28 | if (ioctl(sndsock, BIOCSETIF, &bound_if) > 0) fatal("ioctl err\n"); 29 | #endif 30 | pcount = 0; 31 | 32 | assert(config); 33 | assert(config->srcmac); 34 | 35 | /* Set Ethernet header */ 36 | frame = (uint8_t *)calloc(1, PKTSIZE); 37 | memcpy (frame, config->dstmac, 6 * sizeof (uint8_t)); 38 | memcpy (frame + 6, config->srcmac, 6 * sizeof (uint8_t)); 39 | frame[12] = 0x86; /* IPv6 Ethertype */ 40 | frame[13] = 0xdd; 41 | 42 | /* Set static IP6 header fields */ 43 | outip = (struct ip6_hdr *) (frame + ETH_HDRLEN); 44 | outip->ip6_flow = htonl(0x6<<28|tc<<20|flow); 45 | outip->ip6_src = source6.sin6_addr; 46 | 47 | /* Init yarrp payload struct */ 48 | payload = (struct ypayload *)malloc(sizeof(struct ypayload)); 49 | payload->id = htonl(0x79727036); 50 | payload->instance = config->instance; 51 | 52 | if (config->probe and config->receive) { 53 | pthread_create(&recv_thread, NULL, listener6, this); 54 | /* give listener thread time to startup */ 55 | sleep(1); 56 | } 57 | } 58 | 59 | Traceroute6::~Traceroute6() { 60 | if (config->testing) return; 61 | free(frame); 62 | } 63 | 64 | void Traceroute6::probePrint(struct in6_addr addr, int ttl) { 65 | uint32_t diff = elapsed(); 66 | if (config->probesrc) { 67 | inet_ntop(AF_INET6, &source6.sin6_addr, addrstr, INET6_ADDRSTRLEN); 68 | cout << addrstr << " -> "; 69 | } 70 | inet_ntop(AF_INET6, &addr, addrstr, INET6_ADDRSTRLEN); 71 | cout << addrstr << " ttl: " << ttl << " t=" << diff; 72 | (config->coarse) ? cout << "ms" << endl : cout << "us" << endl; 73 | } 74 | 75 | void 76 | Traceroute6::probe(struct in6_addr addr, int ttl) { 77 | #ifdef _LINUX 78 | struct sockaddr_ll target; 79 | memset(&target, 0, sizeof(target)); 80 | target.sll_ifindex = if_nametoindex(config->int_name); 81 | target.sll_family = AF_PACKET; 82 | memcpy(target.sll_addr, config->srcmac, 6 * sizeof(uint8_t)); 83 | target.sll_halen = 6; 84 | probe(&target, addr, ttl); 85 | #else 86 | probe(NULL, addr, ttl); 87 | #endif 88 | } 89 | 90 | void 91 | Traceroute6::probe(void *target, struct in6_addr addr, int ttl) { 92 | outip->ip6_hlim = ttl; 93 | outip->ip6_dst = addr; 94 | 95 | uint16_t ext_hdr_len = 0; 96 | uint16_t transport_hdr_len = 0; 97 | switch(config->type) { 98 | case TR_ICMP6: 99 | outip->ip6_nxt = IPPROTO_ICMPV6; 100 | transport_hdr_len = sizeof(struct icmp6_hdr); 101 | break; 102 | case TR_UDP6: 103 | outip->ip6_nxt = IPPROTO_UDP; 104 | transport_hdr_len = sizeof(struct udphdr); 105 | break; 106 | case TR_TCP6_SYN: 107 | case TR_TCP6_ACK: 108 | outip->ip6_nxt = IPPROTO_TCP; 109 | transport_hdr_len = sizeof(struct tcphdr); 110 | break; 111 | default: 112 | cerr << "** bad trace type" << endl; 113 | assert(false); 114 | } 115 | 116 | /* Shim in an extension header? */ 117 | if (config->v6_eh != 255) { 118 | if (config->v6_eh == 44) { 119 | make_frag_eh(outip->ip6_nxt); 120 | } else { 121 | make_hbh_eh(outip->ip6_nxt); 122 | } 123 | outip->ip6_nxt = config->v6_eh; 124 | ext_hdr_len = 8; 125 | } 126 | 127 | /* Populate a yarrp payload */ 128 | payload->ttl = ttl; 129 | payload->fudge = 0; 130 | payload->target = addr; 131 | uint32_t diff = elapsed(); 132 | payload->diff = diff; 133 | u_char *data = (u_char *)(frame + ETH_HDRLEN + sizeof(ip6_hdr) 134 | + ext_hdr_len + transport_hdr_len); 135 | memcpy(data, payload, sizeof(struct ypayload)); 136 | 137 | /* Populate transport header */ 138 | packlen = transport_hdr_len + sizeof(struct ypayload); 139 | make_transport(ext_hdr_len); 140 | /* Copy yarrp payload again, after changing fudge for cksum */ 141 | memcpy(data, payload, sizeof(struct ypayload)); 142 | outip->ip6_plen = htons(packlen + ext_hdr_len); 143 | 144 | /* xmit frame */ 145 | if (verbosity > HIGH) { 146 | cout << ">> " << Tr_Type_String[config->type] << " probe: "; 147 | probePrint(addr, ttl); 148 | } 149 | uint16_t framelen = ETH_HDRLEN + sizeof(ip6_hdr) + ext_hdr_len + packlen; 150 | #ifdef _LINUX 151 | if (sendto(sndsock, frame, framelen, 0, (struct sockaddr *)target, 152 | sizeof(struct sockaddr_ll)) < 0) 153 | { 154 | fatal("%s: error: %s", __func__, strerror(errno)); 155 | } 156 | #else 157 | /* use the BPF to send */ 158 | write(sndsock, frame, framelen); 159 | #endif 160 | pcount++; 161 | } 162 | 163 | void 164 | Traceroute6::make_frag_eh(uint8_t nxt) { 165 | void *transport = frame + ETH_HDRLEN + sizeof(ip6_hdr); 166 | struct ip6_frag *eh = (struct ip6_frag *) transport; 167 | eh->ip6f_nxt = nxt; 168 | eh->ip6f_reserved = 0; 169 | eh->ip6f_offlg = 0; 170 | eh->ip6f_ident = 0x8008; 171 | } 172 | 173 | void 174 | Traceroute6::make_hbh_eh(uint8_t nxt) { 175 | uint8_t *transport = frame + ETH_HDRLEN + sizeof(ip6_hdr); 176 | struct ip6_ext *eh = (struct ip6_ext *) transport; 177 | eh->ip6e_nxt = nxt; 178 | eh->ip6e_len = 0; 179 | transport+=2; 180 | struct ip6_opt *opt = (struct ip6_opt *) transport; 181 | opt->ip6o_type = IP6OPT_PADN; 182 | opt->ip6o_len = 4; 183 | transport+=2; 184 | memset(transport, 0, 4); 185 | } 186 | 187 | void 188 | Traceroute6::make_transport(int ext_hdr_len) { 189 | void *transport = frame + ETH_HDRLEN + sizeof(ip6_hdr) + ext_hdr_len; 190 | uint16_t sum = in_cksum((unsigned short *)&(outip->ip6_dst), 16); 191 | if (config->type == TR_ICMP6) { 192 | struct icmp6_hdr *icmp6 = (struct icmp6_hdr *)transport; 193 | icmp6->icmp6_type = ICMP6_ECHO_REQUEST; 194 | icmp6->icmp6_code = 0; 195 | icmp6->icmp6_cksum = 0; 196 | icmp6->icmp6_id = htons(sum); 197 | icmp6->icmp6_seq = htons(pcount); 198 | icmp6->icmp6_cksum = p_cksum(outip, (u_short *) icmp6, packlen); 199 | } else if (config->type == TR_UDP6) { 200 | struct udphdr *udp = (struct udphdr *)transport; 201 | udp->uh_sport = htons(sum); 202 | udp->uh_dport = htons(dstport); 203 | udp->uh_ulen = htons(packlen); 204 | udp->uh_sum = 0; 205 | udp->uh_sum = p_cksum(outip, (u_short *) udp, packlen); 206 | /* set checksum for paris goodness */ 207 | uint16_t crafted_cksum = htons(0xbeef); 208 | payload->fudge = compute_data(udp->uh_sum, crafted_cksum); 209 | udp->uh_sum = crafted_cksum; 210 | } else if (config->type == TR_TCP6_SYN || config->type == TR_TCP6_ACK) { 211 | struct tcphdr *tcp = (struct tcphdr *)transport; 212 | tcp->th_sport = htons(sum); 213 | tcp->th_dport = htons(dstport); 214 | tcp->th_seq = htonl(1); 215 | tcp->th_off = 5; 216 | tcp->th_win = htons(65535); 217 | tcp->th_sum = 0; 218 | tcp->th_x2 = 0; 219 | tcp->th_flags = 0; 220 | tcp->th_urp = htons(0); 221 | if (config->type == TR_TCP6_SYN) 222 | tcp->th_flags |= TH_SYN; 223 | else 224 | tcp->th_flags |= TH_ACK; 225 | tcp->th_sum = p_cksum(outip, (u_short *) tcp, packlen); 226 | /* set checksum for paris goodness */ 227 | uint16_t crafted_cksum = htons(0xbeef); 228 | payload->fudge = compute_data(tcp->th_sum, crafted_cksum); 229 | tcp->th_sum = crafted_cksum; 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /yarrp.1: -------------------------------------------------------------------------------- 1 | .\" 2 | .\" yarrp.1 3 | .\" 4 | .\" Author: Robert Beverly 5 | .\" 6 | .\" Copyright (c) 2016-2024 Robert Beverly 7 | .\" All rights reserved 8 | .\" 9 | .\" 10 | .Dd Sept 27, 2024 11 | .Dt YARRP 1 12 | .Os 13 | .Sh NAME 14 | .Nm yarrp 15 | .Nd high-speed active IPv4/IPv6 network topology prober 16 | .Sh SYNOPSIS 17 | .Nm 18 | .Bk -words 19 | .Op Fl hvQT 20 | .Op Fl i Ar target_file 21 | .Op Fl o Ar outfile 22 | .Op Fl r Ar rate 23 | .Op Fl t Ar tr_type 24 | .Op Fl c Ar tr_count 25 | .Op Fl S Ar seed 26 | .Op Fl E Ar instance 27 | .Op Fl p Ar dst_port 28 | .Op Fl b Ar bgp_rib 29 | .Op Fl B Ar blocklist 30 | .Op Fl l Ar min_ttl 31 | .Op Fl m Ar max_ttl 32 | .Op Fl F Ar fill_ttl 33 | .Op Fl n Ar nbr_ttl 34 | .Op Fl s Ar sequential 35 | .Op Fl Z Ar poisson 36 | .Op Fl a Ar src_addr 37 | .Op Fl I Ar interface 38 | .Op Fl M Ar src_mac 39 | .Op Fl G Ar dst_mac 40 | .Op Fl g Ar v6_gran 41 | .Op Fl X Ar v6_eh 42 | .Op Ar subnet(s) 43 | .Sh DESCRIPTION 44 | .Nm 45 | (Yelling at Random Routers Progressively) is a high-speed active 46 | traceroute-style network topology discovery tool. To achieve its high probing 47 | rates, 48 | .Nm 49 | is stateless and randomizes the order of probed destinations and 50 | TTLs. By spreading probes, 51 | .Nm 52 | distributes load and attempts to avoid 53 | network rate-limiting. Yarrp supports both IPv4 and IPv6 54 | and can send probes of any transport type (TCP, UDP-paris, or ICMP-paris). 55 | .Pp 56 | .Sh OPTIONS 57 | The set of IPv4 or IPv6 destination targets to probe may be specified 58 | in one of three ways: 59 | .Bl -tag -width Ds 60 | .It Ar subnet(s) 61 | Probes a target in each /24 (IPv4), or 62 | each /48 (IPv6), of the specified subnets. 63 | .It Fl i Ar target_file 64 | Input list (one address per line) of explicit targets; accepts stdin. 65 | .It Fl Q 66 | Internet-wide scanning. Probes an address in each /24 (IPv4) or each /48 (IPv6) 67 | (use with caution). 68 | .El 69 | .Pp 70 | The general options are as follows: 71 | .Bl -tag -width Ds 72 | .It Fl h 73 | print command line options and a synopsis of each. 74 | .It Fl v 75 | verbose (use multiple times to increase verbosity) 76 | .It Fl T 77 | test mode (default: off) 78 | .It Fl o Ar outfile 79 | output file for probing results; accepts stdout. (default: output.yrp) 80 | .It Fl r Ar rate 81 | set packet per second probing rate (default: 10pps) 82 | .It Fl t Ar tr_type 83 | set probe type: TCP_ACK, TCP_SYN, UDP, ICMP, ICMP_REPLY (default: TCP_ACK) 84 | .It Fl c Ar tr_count 85 | set number of traces to issue (default: unlimited) 86 | .It Fl S Ar seed 87 | set permutation random seed (default: timestamp) 88 | .It Fl E Ar instance 89 | set instance (default: 0) 90 | .It Fl p Ar dst_port 91 | use specified transport destination port (default: 80) 92 | .It Fl a Ar src_addr 93 | set source IP address (default: auto) 94 | .El 95 | .Pp 96 | The target options are as follows: 97 | .Bl -tag -width Ds 98 | .It Fl b Ar bgp_rib 99 | read BGP RIB (Potaroo text format) (default: none) 100 | .It Fl B Ar blocklist 101 | read list of prefixes to skip (default: none) 102 | .El 103 | .Pp 104 | The options to control TTLs probed are: 105 | .Bl -tag -width Ds 106 | .It Fl l Ar min_ttl 107 | set minimum TTL (default: 1) 108 | .It Fl m Ar max_ttl 109 | set maximum TTL, must be a power of 2 (default: 16) 110 | .It Fl F Ar fill_ttl 111 | set fill mode maximum TTL (default: 32) 112 | .It Fl s 113 | send probes sequentially (default: random) 114 | .It Fl n Ar nbr_ttl 115 | enable neighborhood enhancement and set local neighborhood TTL (default: off) 116 | .It Fl Z Ar poisson 117 | choose TTLs from a Poisson distribution with specified lambda (default: uniform) 118 | .El 119 | .Pp 120 | The IPv6-specific options are as follows: 121 | .Bl -tag -width Ds 122 | .It Fl I Ar interface 123 | network interface to use (required) 124 | .It Fl t Ar tr_type 125 | set probe type: ICMP6, UDP6, TCP6_SYN, TCP6_ACK (required) 126 | .It Fl M Ar src_mac 127 | MAC address of source (required if auto discovery fails) 128 | .It Fl G Ar dst_mac 129 | MAC address of gateway router (required if auto discovery fails) 130 | .It Fl g Ar v6_gran 131 | Granularity at which to probe input IPv6 prefixes (default: /50) 132 | .It Fl X Ar v6_eh 133 | Set extension header type to add (default: none) 134 | .El 135 | .Sh OUTPUT 136 | .Nm 137 | writes probe responses to the specified output file in a delimited 138 | ASCII format as they are received, one response per line. Because 139 | .Nm 140 | randomizes its probing, results will be similarly randomized. 141 | To determine all of the responses for a single target destination, it 142 | is necessary to filter and collate responses. The included 143 | yrp2warts utility (provided as both python and C++) performs this reconstitution and produces output 144 | in the standard warts binary format. 145 | .Sh TTLs 146 | By default, 147 | .Nm 148 | randomly permutes the space of targets and TTLs, 149 | thereby probing each target with TTLs from min_ttl to max_ttl in a random 150 | order. Note that because of the way 151 | .Nm 152 | permutes the probe order, max_ttl must be a power of two. 153 | .Pp 154 | Four options modify this behavior. The sequential option 155 | (-s) disables random probing and instead probes sequentially. The nbr_ttl 156 | option (-n) is an optimization that stops probing low TTLs within the local 157 | neighborhood of the prober once 158 | .Nm 159 | determines that it is not 160 | discovering any new interfaces within that neighborhood. In 161 | fill mode (-F), 162 | .Nm 163 | will probe, up to a maximum TTL of fill_ttl, the next 164 | hop beyond 165 | max_ttl if it receives a response for a probe with TTL 166 | greater than or equal to max_ttl. 167 | .Pp 168 | Finally, the -Z option specifies a lambda parameter for a Poisson 169 | distribution. 170 | .Nm 171 | will iterate through all TTLs, but the probability of probing 172 | a particular TTL follows a Poisson distribution with the given lambda. 173 | This mode is intended to maximize router discovery yield, as 174 | the majority of Internet routers are concentrated in a particular 175 | TTL range. 176 | .Sh EXAMPLES 177 | The command: 178 | .Pp 179 | .in +.3i 180 | yarrp -i targets -o test.yrp -r 100 181 | .in -.3i 182 | .Pp 183 | will send TCP_ACK topology probes in a randomly-permuted order to the IPv4 184 | targets in file "targets" at a rate of 100pps, and write results to 185 | file "test.yrp". 186 | .Pp 187 | The command: 188 | .Pp 189 | .in +.3i 190 | yarrp -o scan.yrp -t ICMP -v -m 16 205.155.0.0/16 191 | .in -.3i 192 | .Pp 193 | will send ICMP topology probes in a randomly-permuted order to all 194 | destinations within the prefix 205.155.0.0/16, from TTL 1 to 16 195 | at the default rate of 10pps. Verbosity is switched on so that 196 | .Nm 197 | will report probe and response data to stdout. The results 198 | will be written to the file "scan.yrp". 199 | .Pp 200 | The command: 201 | .Pp 202 | .in +.3i 203 | yarrp -o scan2.yrp -t ICMP -b bgptable.txt 1.0.0.0/8 204 | .in -.3i 205 | .Pp 206 | will send ICMP topology probes in a randomly-permuted order to all 207 | destinations within the prefix 1.0.0.0/8, if the destination 208 | has a route in the BGP routing table "bgptable.txt". The routing 209 | table file must be plain-text in Potaroo format (the most recent 210 | table is available from https://bgp.potaroo.net/as6447/bgptable.txt). 211 | The results will be written to the file "scan2.yrp". 212 | .Pp 213 | The command: 214 | .Pp 215 | .in +.3i 216 | yarrp -t UDP6 -I eth0 -i targets6 -o test6.yrp 217 | .in -.3i 218 | .Pp 219 | will send UDP probes in a randomly-permuted order to the set of 220 | IPv6 targets in the file "targets6", and write the results to the file 221 | "test6.yrp". 222 | .Pp 223 | .in -.5i 224 | .Sh SEE ALSO 225 | .Xr yrp2warts.py 1 226 | .Xr warts2yrp.py 1 227 | .Rs 228 | .%A "R. Beverly" 229 | .%T "Yarrp'ing the Internet: Randomized High-Speed Active Topology Discovery" 230 | .%O "Proc. ACM/SIGCOMM Internet Measurement Conference 2016" 231 | .Re 232 | .Rs 233 | .%A "R. Beverly, R. Durairajan, D. Plonka, and J.P. Rohrer" 234 | .%T "In the IP of the Beholder: Strategies for Active IPv6 Topology Discovery" 235 | .%O "Proc. ACM/SIGCOMM Internet Measurement Conference 2018" 236 | .Re 237 | .Rs 238 | .%A "E. C. Rye, and R. Beverly" 239 | .%T "Discovering the IPv6 Network Periphery" 240 | .%O "Proc. Passive and Active Measurement 2020" 241 | .Re 242 | .Rs 243 | .%A "K. Vermeulen, et al." 244 | .%T "Diamond-Miner: Comprehensive Discovery of the Internet's Topology Diamonds" 245 | .%O "Proc. USENIX NSDI 2020" 246 | .Re 247 | .Sh AUTHORS 248 | .Nm 249 | is written by Robert Beverly . Ionut Luculescu contributed 250 | support for IPv4 UDP probing. Eric Gaston contributed support for IPv6 probing. 251 | Oliver Gasser contributed proper rate limiting patches. 252 | -------------------------------------------------------------------------------- /trace4.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | Program: $Id: trace.cpp 39 2015-12-30 20:28:36Z rbeverly $ 3 | Date: $Date: 2015-12-30 12:28:36 -0800 (Wed, 30 Dec 2015) $ 4 | Description: traceroute class 5 | ****************************************************************************/ 6 | #include "yarrp.h" 7 | 8 | Traceroute4::Traceroute4(YarrpConfig *_config, Stats *_stats) : Traceroute(_config, _stats) 9 | { 10 | if (config->testing) return; 11 | memset(&source, 0, sizeof(struct sockaddr_in)); 12 | if (config->probesrc) { 13 | source.sin_family = AF_INET; 14 | if (inet_pton(AF_INET, config->probesrc, &source.sin_addr) != 1) 15 | fatal("** Bad source address."); 16 | cout << ">> Using IP source: " << config->probesrc << endl; 17 | } else { 18 | infer_my_ip(&source); 19 | } 20 | inet_ntop(AF_INET, &source.sin_addr, addrstr, INET_ADDRSTRLEN); 21 | config->set("SourceIP", addrstr, true); 22 | payloadlen = 0; 23 | outip = (struct ip *)calloc(1, PKTSIZE); 24 | outip->ip_v = IPVERSION; 25 | outip->ip_hl = sizeof(struct ip) >> 2; 26 | outip->ip_src.s_addr = source.sin_addr.s_addr; 27 | sndsock = raw_sock(&source); 28 | if (config->probe and config->receive) { 29 | lock(); /* grab mutex; make listener thread block. */ 30 | pthread_create(&recv_thread, NULL, listener, this); 31 | } 32 | } 33 | 34 | Traceroute4::~Traceroute4() { 35 | if (outip) 36 | free(outip); 37 | } 38 | 39 | void Traceroute4::probePrint(struct in_addr *targ, int ttl) { 40 | uint32_t diff = elapsed(); 41 | if (config->probesrc) 42 | cout << inet_ntoa(source.sin_addr) << " -> "; 43 | cout << inet_ntoa(*targ) << " ttl: "; 44 | cout << ttl; 45 | if (config->instance) 46 | cout << " i=" << (int) config->instance; 47 | cout << " t=" << diff; 48 | (config->coarse) ? cout << "ms" << endl : cout << "us" << endl; 49 | } 50 | 51 | void 52 | Traceroute4::probe(const char *targ, int ttl) { 53 | struct sockaddr_in target; 54 | memset(&target, 0, sizeof(target)); 55 | target.sin_family = AF_INET; 56 | #ifdef _BSD 57 | target.sin_len = sizeof(target); 58 | #endif 59 | inet_aton(targ, &(target.sin_addr)); 60 | probe(&target, ttl); 61 | } 62 | 63 | void 64 | Traceroute4::probe(uint32_t addr, int ttl) { 65 | struct sockaddr_in target; 66 | memset(&target, 0, sizeof(target)); 67 | target.sin_family = AF_INET; 68 | #ifdef _BSD 69 | target.sin_len = sizeof(target); 70 | #endif 71 | target.sin_addr.s_addr = addr; 72 | probe(&target, ttl); 73 | } 74 | 75 | void 76 | Traceroute4::probe(struct sockaddr_in *target, int ttl) { 77 | outip->ip_ttl = ttl; 78 | outip->ip_id = htons(ttl + (config->instance << 8)); 79 | outip->ip_off = 0; // htons(IP_DF); 80 | outip->ip_dst.s_addr = (target->sin_addr).s_addr; 81 | outip->ip_sum = 0; 82 | if (TR_UDP == config->type) { 83 | probeUDP(target, ttl); 84 | } else if ( (TR_ICMP == config->type) || (TR_ICMP_REPLY == config->type) ) { 85 | probeICMP(target, ttl); 86 | } else if ( (TR_TCP_SYN == config->type) || (TR_TCP_ACK == config->type) ) { 87 | probeTCP(target, ttl); 88 | } else { 89 | cerr << "** bad trace type:" << config->type << endl; 90 | assert(false); 91 | } 92 | } 93 | 94 | void 95 | Traceroute4::probeUDP(struct sockaddr_in *target, int ttl) { 96 | unsigned char *ptr = (unsigned char *)outip; 97 | struct udphdr *udp = (struct udphdr *)(ptr + (outip->ip_hl << 2)); 98 | unsigned char *data = (unsigned char *)(ptr + (outip->ip_hl << 2) + sizeof(struct udphdr)); 99 | 100 | uint32_t diff = elapsed(); 101 | payloadlen = 2; 102 | /* encode MSB of timestamp in UDP payload length */ 103 | if (diff >> 16) 104 | payloadlen += (diff>>16); 105 | if (verbosity > HIGH) { 106 | cout << ">> UDP probe: "; 107 | probePrint(&target->sin_addr, ttl); 108 | } 109 | 110 | packlen = sizeof(struct ip) + sizeof(struct udphdr) + payloadlen; 111 | 112 | outip->ip_p = IPPROTO_UDP; 113 | #if defined(_BSD) && !defined(_NEW_FBSD) 114 | outip->ip_len = packlen; 115 | outip->ip_off = IP_DF; 116 | #else 117 | outip->ip_len = htons(packlen); 118 | outip->ip_off = ntohs(IP_DF); 119 | #endif 120 | /* encode destination IPv4 address as cksum(ipdst) */ 121 | uint16_t dport = in_cksum((unsigned short *)&(outip->ip_dst), 4); 122 | udp->uh_sport = htons(dport); 123 | udp->uh_dport = htons(dstport); 124 | udp->uh_ulen = htons(sizeof(struct udphdr) + payloadlen); 125 | udp->uh_sum = 0; 126 | 127 | outip->ip_sum = htons(in_cksum((unsigned short *)outip, 20)); 128 | 129 | /* compute UDP checksum */ 130 | memset(data, 0, 2); 131 | u_short len = sizeof(struct udphdr) + payloadlen; 132 | udp->uh_sum = p_cksum(outip, (u_short *) udp, len); 133 | 134 | /* encode LSB of timestamp in checksum */ 135 | uint16_t crafted_cksum = diff & 0xFFFF; 136 | /* craft payload such that the new cksum is correct */ 137 | uint16_t crafted_data = compute_data(udp->uh_sum, crafted_cksum); 138 | memcpy(data, &crafted_data, 2); 139 | if (crafted_cksum == 0x0000) 140 | crafted_cksum = 0xFFFF; 141 | udp->uh_sum = crafted_cksum; 142 | 143 | if (sendto(sndsock, (char *)outip, packlen, 0, (struct sockaddr *)target, sizeof(*target)) < 0) { 144 | cout << __func__ << "(): error: " << strerror(errno) << endl; 145 | cout << ">> UDP probe: " << inet_ntoa(target->sin_addr) << " ttl: "; 146 | cout << ttl << " t=" << diff << endl; 147 | } 148 | } 149 | 150 | void 151 | Traceroute4::probeTCP(struct sockaddr_in *target, int ttl) { 152 | unsigned char *ptr = (unsigned char *)outip; 153 | struct tcphdr *tcp = (struct tcphdr *)(ptr + (outip->ip_hl << 2)); 154 | 155 | packlen = sizeof(struct ip) + sizeof(struct tcphdr) + payloadlen; 156 | outip->ip_p = IPPROTO_TCP; 157 | #if defined(_BSD) && !defined(_NEW_FBSD) 158 | outip->ip_len = packlen; 159 | outip->ip_off = 0; //IP_DF; 160 | #else 161 | outip->ip_len = htons(packlen); 162 | #endif 163 | /* encode destination IPv4 address as cksum(ipdst) */ 164 | uint16_t dport = in_cksum((unsigned short *)&(outip->ip_dst), 4); 165 | tcp->th_sport = htons(dport); 166 | tcp->th_dport = htons(dstport); 167 | /* encode send time into seq no as elapsed milliseconds */ 168 | uint32_t diff = elapsed(); 169 | if (verbosity > HIGH) { 170 | cout << ">> TCP probe: "; 171 | probePrint(&target->sin_addr, ttl); 172 | } 173 | tcp->th_seq = htonl(diff); 174 | tcp->th_off = 5; 175 | tcp->th_win = htons(0xFFFE); 176 | tcp->th_sum = 0; 177 | /* don't want to set SYN, lest we be tagged as SYN flood. */ 178 | if (TR_TCP_SYN == config->type) { 179 | tcp->th_flags |= TH_SYN; 180 | } else { 181 | tcp->th_flags |= TH_ACK; 182 | tcp->th_ack = htonl(target->sin_addr.s_addr); 183 | } 184 | /* 185 | * explicitly computing cksum probably not required on most machines 186 | * these days as offloaded by OS or NIC. but we'll be safe. 187 | */ 188 | outip->ip_sum = htons(in_cksum((unsigned short *)outip, 20)); 189 | /* 190 | * bsd rawsock requires host ordered len and offset; rewrite here as 191 | * chksum must be over htons() versions 192 | */ 193 | u_short len = sizeof(struct tcphdr) + payloadlen; 194 | tcp->th_sum = p_cksum(outip, (u_short *) tcp, len); 195 | if (sendto(sndsock, (char *)outip, packlen, 0, (struct sockaddr *)target, sizeof(*target)) < 0) { 196 | cout << __func__ << "(): error: " << strerror(errno) << endl; 197 | cout << ">> TCP probe: " << inet_ntoa(target->sin_addr) << " ttl: "; 198 | cout << ttl << " t=" << diff << endl; 199 | } 200 | } 201 | 202 | void 203 | Traceroute4::probeICMP(struct sockaddr_in *target, int ttl) { 204 | unsigned char *ptr = (unsigned char *)outip; 205 | struct icmp *icmp = (struct icmp *)(ptr + (outip->ip_hl << 2)); 206 | unsigned char *data = (unsigned char *)(ptr + (outip->ip_hl << 2) + ICMP_MINLEN); 207 | 208 | payloadlen = 2; 209 | packlen = sizeof(struct ip) + ICMP_MINLEN + payloadlen; 210 | outip->ip_p = IPPROTO_ICMP; 211 | outip->ip_len = htons(packlen); 212 | #if defined(_BSD) && !defined(_NEW_FBSD) 213 | outip->ip_len = packlen; 214 | outip->ip_off = 0; //IP_DF; 215 | #else 216 | outip->ip_len = htons(packlen); 217 | #endif 218 | /* encode send time into icmp id and seq as elapsed milli/micro seconds */ 219 | uint32_t diff = elapsed(); 220 | if (verbosity > HIGH) { 221 | cout << ">> ICMP probe: "; 222 | probePrint(&target->sin_addr, ttl); 223 | } 224 | icmp->icmp_type = ICMP_ECHO; 225 | if (TR_ICMP_REPLY == config->type) 226 | icmp->icmp_type = ICMP_ECHOREPLY; 227 | icmp->icmp_code = 0; 228 | icmp->icmp_cksum = 0; 229 | icmp->icmp_id = htons(diff & 0xFFFF); 230 | icmp->icmp_seq = htons((diff >> 16) & 0xFFFF); 231 | outip->ip_sum = htons(in_cksum((unsigned short *)outip, 20)); 232 | 233 | /* compute ICMP checksum */ 234 | memset(data, 0, 2); 235 | u_short len = ICMP_MINLEN + payloadlen; 236 | icmp->icmp_cksum = in_cksum((u_short *) icmp, len); 237 | 238 | /* encode cksum(ipdst) into checksum */ 239 | uint16_t crafted_cksum = in_cksum((unsigned short *)&(outip->ip_dst), 4); 240 | /* craft payload such that the new cksum is correct */ 241 | uint16_t crafted_data = compute_data(icmp->icmp_cksum, crafted_cksum); 242 | memcpy(data, &crafted_data, 2); 243 | if (crafted_cksum == 0x0000) 244 | crafted_cksum = 0xFFFF; 245 | icmp->icmp_cksum = crafted_cksum; 246 | 247 | if (sendto(sndsock, (char *)outip, packlen, 0, (struct sockaddr *)target, sizeof(*target)) < 0) { 248 | cout << __func__ << "(): error: " << strerror(errno) << endl; 249 | cout << ">> ICMP probe: " << inet_ntoa(target->sin_addr) << " ttl: "; 250 | cout << ttl << " t=" << diff << endl; 251 | } 252 | } 253 | --------------------------------------------------------------------------------