From 9bf2ec3884e87cd8a25b6c0222b508c5affacf67 Mon Sep 17 00:00:00 2001 From: david Date: Mon, 19 Sep 2011 18:31:46 +0000 Subject: [PATCH] Merge from /nmap-exp/luis/nmap-os6. svn merge --ignore-ancestry svn://svn.insecure.org/nmap@26621 svn://svn.insecure.org/nmap-exp/luis/nmap-os6 This is the IPv6 OS detection branch. "nmap -6 -O" works now, though at this point it only prints fingerprints and not OS guesses, because we need to collect more submissions. --- FPEngine.cc | 2582 ++++++++++++++++++++++++++ FPEngine.h | 437 +++++ FPmodel.cc | 1590 ++++++++++++++++ FingerPrintResults.cc | 48 +- FingerPrintResults.h | 35 +- Makefile.in | 24 +- NmapOps.cc | 3 +- NmapOps.h | 6 + Target.cc | 27 +- Target.h | 9 +- configure | 127 ++ configure.ac | 61 + docs/3rd-party-licenses.txt | 37 + global_structures.h | 12 +- liblinear/COPYRIGHT | 31 + liblinear/Makefile | 36 + liblinear/Makefile.win | 30 + liblinear/README | 485 +++++ liblinear/blas/Makefile | 22 + liblinear/blas/blas.h | 25 + liblinear/blas/blasp.h | 430 +++++ liblinear/blas/daxpy.c | 49 + liblinear/blas/ddot.c | 50 + liblinear/blas/dnrm2.c | 62 + liblinear/blas/dscal.c | 44 + liblinear/liblinear.vcxproj | 95 + liblinear/linear.cpp | 2382 ++++++++++++++++++++++++ liblinear/linear.def | 18 + liblinear/linear.h | 73 + liblinear/predict.c | 218 +++ liblinear/train.c | 340 ++++ liblinear/tron.cpp | 235 +++ liblinear/tron.h | 34 + libnetutil/ARPHeader.cc | 344 ++++ libnetutil/ARPHeader.h | 251 +++ libnetutil/ApplicationLayerElement.h | 102 + libnetutil/DataLinkLayerElement.h | 101 + libnetutil/DestOptsHeader.cc | 126 ++ libnetutil/DestOptsHeader.h | 117 ++ libnetutil/EthernetHeader.cc | 250 +++ libnetutil/EthernetHeader.h | 164 ++ libnetutil/FragmentHeader.cc | 243 +++ libnetutil/FragmentHeader.h | 144 ++ libnetutil/HopByHopHeader.cc | 418 +++++ libnetutil/HopByHopHeader.h | 153 ++ libnetutil/ICMPHeader.h | 114 ++ libnetutil/ICMPv4Header.cc | 1209 ++++++++++++ libnetutil/ICMPv4Header.h | 561 ++++++ libnetutil/ICMPv6Header.cc | 1158 ++++++++++++ libnetutil/ICMPv6Header.h | 690 +++++++ libnetutil/ICMPv6Option.cc | 357 ++++ libnetutil/ICMPv6Option.h | 266 +++ libnetutil/ICMPv6RRBody.cc | 142 ++ libnetutil/ICMPv6RRBody.h | 231 +++ libnetutil/IPv4Header.cc | 654 +++++++ libnetutil/IPv4Header.h | 250 +++ libnetutil/IPv6ExtensionHeader.h | 112 ++ libnetutil/IPv6Header.cc | 511 +++++ libnetutil/IPv6Header.h | 203 ++ libnetutil/Makefile.in | 4 +- libnetutil/NetworkLayerElement.cc | 93 + libnetutil/NetworkLayerElement.h | 123 ++ libnetutil/PacketElement.cc | 101 + libnetutil/PacketElement.h | 299 +++ libnetutil/PacketParser.cc | 1708 +++++++++++++++++ libnetutil/PacketParser.h | 162 ++ libnetutil/RawData.cc | 211 +++ libnetutil/RawData.h | 121 ++ libnetutil/RoutingHeader.cc | 340 ++++ libnetutil/RoutingHeader.h | 207 +++ libnetutil/TCPHeader.cc | 963 ++++++++++ libnetutil/TCPHeader.h | 290 +++ libnetutil/TransportLayerElement.cc | 156 ++ libnetutil/TransportLayerElement.h | 121 ++ libnetutil/UDPHeader.cc | 329 ++++ libnetutil/UDPHeader.h | 158 ++ libnetutil/libnetutil.vcxproj | 42 + libnetutil/netutil.cc | 8 +- libnetutil/netutil.h | 6 +- libnetutil/npacket.cc | 119 ++ libnetutil/npacket.h | 128 ++ libpcre/config.h.in | 3 + mswin32/nmap.sln | 11 +- mswin32/nmap.vcxproj | 15 +- nmap.cc | 13 +- nmap.h | 4 +- nse_nmaplib.cc | 2 +- osscan.cc | 61 +- osscan.h | 14 +- osscan2.cc | 306 +-- osscan2.h | 23 +- output.cc | 210 ++- todo/nmap.txt | 8 + 93 files changed, 24665 insertions(+), 222 deletions(-) create mode 100644 FPEngine.cc create mode 100644 FPEngine.h create mode 100644 FPmodel.cc create mode 100644 liblinear/COPYRIGHT create mode 100644 liblinear/Makefile create mode 100644 liblinear/Makefile.win create mode 100644 liblinear/README create mode 100644 liblinear/blas/Makefile create mode 100644 liblinear/blas/blas.h create mode 100644 liblinear/blas/blasp.h create mode 100644 liblinear/blas/daxpy.c create mode 100644 liblinear/blas/ddot.c create mode 100644 liblinear/blas/dnrm2.c create mode 100644 liblinear/blas/dscal.c create mode 100755 liblinear/liblinear.vcxproj create mode 100644 liblinear/linear.cpp create mode 100644 liblinear/linear.def create mode 100644 liblinear/linear.h create mode 100644 liblinear/predict.c create mode 100644 liblinear/train.c create mode 100644 liblinear/tron.cpp create mode 100644 liblinear/tron.h create mode 100644 libnetutil/ARPHeader.cc create mode 100644 libnetutil/ARPHeader.h create mode 100644 libnetutil/ApplicationLayerElement.h create mode 100755 libnetutil/DataLinkLayerElement.h create mode 100644 libnetutil/DestOptsHeader.cc create mode 100644 libnetutil/DestOptsHeader.h create mode 100755 libnetutil/EthernetHeader.cc create mode 100755 libnetutil/EthernetHeader.h create mode 100644 libnetutil/FragmentHeader.cc create mode 100644 libnetutil/FragmentHeader.h create mode 100644 libnetutil/HopByHopHeader.cc create mode 100644 libnetutil/HopByHopHeader.h create mode 100644 libnetutil/ICMPHeader.h create mode 100755 libnetutil/ICMPv4Header.cc create mode 100755 libnetutil/ICMPv4Header.h create mode 100755 libnetutil/ICMPv6Header.cc create mode 100755 libnetutil/ICMPv6Header.h create mode 100755 libnetutil/ICMPv6Option.cc create mode 100755 libnetutil/ICMPv6Option.h create mode 100755 libnetutil/ICMPv6RRBody.cc create mode 100755 libnetutil/ICMPv6RRBody.h create mode 100644 libnetutil/IPv4Header.cc create mode 100644 libnetutil/IPv4Header.h create mode 100644 libnetutil/IPv6ExtensionHeader.h create mode 100755 libnetutil/IPv6Header.cc create mode 100644 libnetutil/IPv6Header.h create mode 100644 libnetutil/NetworkLayerElement.cc create mode 100644 libnetutil/NetworkLayerElement.h create mode 100644 libnetutil/PacketElement.cc create mode 100644 libnetutil/PacketElement.h create mode 100644 libnetutil/PacketParser.cc create mode 100644 libnetutil/PacketParser.h create mode 100644 libnetutil/RawData.cc create mode 100644 libnetutil/RawData.h create mode 100644 libnetutil/RoutingHeader.cc create mode 100644 libnetutil/RoutingHeader.h create mode 100644 libnetutil/TCPHeader.cc create mode 100644 libnetutil/TCPHeader.h create mode 100644 libnetutil/TransportLayerElement.cc create mode 100644 libnetutil/TransportLayerElement.h create mode 100644 libnetutil/UDPHeader.cc create mode 100644 libnetutil/UDPHeader.h create mode 100644 libnetutil/npacket.cc create mode 100644 libnetutil/npacket.h diff --git a/FPEngine.cc b/FPEngine.cc new file mode 100644 index 0000000000..ce8ef60f65 --- /dev/null +++ b/FPEngine.cc @@ -0,0 +1,2582 @@ + +/*************************************************************************** + * FPEngine.cc -- Routines used for IPv6 OS detection via TCP/IP * + * fingerprinting. * For more information on how this works in Nmap, see * + * http://nmap.org/osdetect/ * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ + +/* $Id$ */ + +#include "FPEngine.h" +#include "Target.h" +#include "NmapOps.h" +#include "nmap_error.h" +#include "osscan.h" +#include "libnetutil/npacket.h" +#include "linear.h" +extern NmapOps o; + + +/****************************************************************************** + * Globals. * + ******************************************************************************/ + +/* This is the global network controller. FPHost classes use it to request + * network resources and schedule packet transmissions. */ +FPNetworkControl global_netctl; + + +/****************************************************************************** + * Implementation of class FPNetworkControl. * + ******************************************************************************/ +FPNetworkControl::FPNetworkControl() { + memset(&this->nsp, 0, sizeof(nsock_pool)); + memset(&this->pcap_nsi, 0, sizeof(pcap_nsi)); + memset(&this->pcap_ev_id, 0, sizeof(nsock_event_id)); + this->nsock_init = false; + this->rawsd = -1; + this->probes_sent = 0; + this->responses_recv = 0; + this->probes_timedout = 0; + this->cc_cwnd = 0; + this->cc_ssthresh = 0; +} + + +FPNetworkControl::~FPNetworkControl() { + if (this->nsock_init) { + nsock_event_cancel(this->nsp, this->pcap_ev_id, 0); + nsp_delete(this->nsp); + this->nsock_init = false; + } +} + + +/* (Re)-Initialize object's state (default parameter setup and nsock + * initialization). */ +void FPNetworkControl::init(const char *ifname, devtype iftype) { + + /* Init congestion control parameters */ + this->cc_init(); + + /* If there was a previous nsock pool, delete it */ + if (this->pcap_nsi) { + nsi_delete(this->pcap_nsi, NSOCK_PENDING_SILENT); + } + if (this->nsock_init) { + nsock_event_cancel(this->nsp, this->pcap_ev_id, 0); + nsp_delete(this->nsp); + } + + /* Create a new nsock pool */ + if ((this->nsp = nsp_new(NULL)) == NULL) + fatal("Unable to obtain an Nsock pool"); + + /* Set Trace level */ + if (o.packetTrace()) { + nsp_settrace(this->nsp, NULL, NSOCK_TRACE_LEVEL, o.getStartTime()); + } + + /* Allow broadcast addresses */ + nsp_setbroadcast(this->nsp, 1); + + /* Allocate an NSI for packet capture */ + this->pcap_nsi = nsi_new(this->nsp, NULL); + this->first_pcap_scheduled = false; + + /* Flag it as already initialized so we free this nsp next time */ + this->nsock_init = true; + + /* Obtain raw socket or check that we can obtain an eth descriptor. */ + if ((o.sendpref & PACKET_SEND_ETH) && iftype == devt_ethernet && ifname != NULL) { + /* We don't need to store the eth handler because FPProbes come with a + * suitable one (FPProbes::getEthernet()), we just attempt to obtain one + * to see if it fails. */ + if (eth_open_cached(ifname) == NULL) + fatal("dnet: failed to open device %s", ifname); + this->rawsd = -1; + } else { +#ifdef WIN32 + win32_fatal_raw_sockets(ifname); +#endif + if (this->rawsd >= 0) + close(this->rawsd); + if ((this->rawsd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) + pfatal("Couldn't obtain raw socket in %s", __func__); + broadcast_socket(this->rawsd); +#ifndef WIN32 + sethdrinclude(this->rawsd); +#endif + } + + /* De-register existing callers */ + while (this->callers.size() > 0) { + this->callers.pop_back(); + } + return; +} + + +/* This function initializes the controller's congestion control parameters. + * The network controller uses TCP's Slow Start and Congestion Avoidance + * algorithms from RFC 5681 (slightly modified for convenience). + * + * As the OS detection process does not open full TCP connections, we can't just + * use ACKs (or the lack of ACKs) to increase or decrease the congestion window + * so we use probe responses. Every time we get a response to an OS detection + * probe, we treat it as if it was a TCP ACK in TCP's congestion control. + * + * Note that the initial Congestion Window is set to the number of timed + * probes that we send to each target. This is necessary since we need to + * know for sure that we can send that many packets in order to transmit them. + * Otherwise, we could fail to deliver the probes 100ms apart. */ +int FPNetworkControl::cc_init() { + this->probes_sent = 0; + this->responses_recv = 0; + this->probes_timedout = 0; + this->cc_cwnd = OSSCAN_INITIAL_CWND; + this->cc_ssthresh = OSSCAN_INITIAL_SSTHRESH; + return OP_SUCCESS; +} + + +/* This method is used to indicate that we have scheduled the transmission of + * one or more packets. This is used in congestion control to determine the + * number of outstanding probes (number of probes sent but not answered yet) + * and therefore, the effective transmission window. @param pkts indicates the + * number of packets that were scheduled. Returns OP_SUCCESS on success and + * OP_FAILURE in case of error. */ +int FPNetworkControl::cc_update_sent(int pkts = 1) { + if (pkts <= 0) + return OP_FAILURE; + this->probes_sent+=pkts; + return OP_SUCCESS; +} + + +/* This method is used to indicate that a drop has occurred. In TCP, drops are + * detected by the absence of an ACK. However, we can't use that, since it is + * very likely that our targets do not respond to some of our OS detection + * probes intentionally. For this reason, we consider that a drop has occurred + * when we receive a response for a probe that has already suffered one + * retransmission (first transmission got dropped in transit, some later + * transmission made it to the host and it responded). So when we detect a drop + * we do the same as TCP, adjust the congestion window and the slow start + * threshold. */ +int FPNetworkControl::cc_report_drop() { +/* FROM RFC 5681 + + When a TCP sender detects segment loss using the retransmission timer + and the given segment has not yet been resent by way of the + retransmission timer, the value of ssthresh MUST be set to no more + than the value given in equation (4): + + ssthresh = max (FlightSize / 2, 2*SMSS) (4) + + where, as discussed above, FlightSize is the amount of outstanding + data in the network. + + On the other hand, when a TCP sender detects segment loss using the + retransmission timer and the given segment has already been + retransmitted by way of the retransmission timer at least once, the + value of ssthresh is held constant. + */ + int probes_outstanding = this->probes_sent - this->responses_recv - this->probes_timedout; + this->cc_ssthresh = MAX(probes_outstanding, OSSCAN_INITIAL_CWND); + this->cc_cwnd = OSSCAN_INITIAL_CWND; + return OP_SUCCESS; +} + + +/* This method is used to indicate that a response to a previous probe was + * received. For us this is like getting and ACK in TCP congestion control, so + * we update the congestion window (increase by one packet if we are in slow + * start or increase it by a small percentage of a packet if we are in + * congestion avoidance). */ +int FPNetworkControl::cc_update_received() { + this->responses_recv++; + /* If we are in Slow Start, increment congestion window by one packet. + * (Note that we treat probe responses the same way TCP CC treats ACKs). */ + if (this->cc_cwnd < this->cc_ssthresh) { + this->cc_cwnd += 1; + /* Otherwise we are in Congestion Avoidance and CWND is incremented slowly, + * approximately one packet per RTT */ + } else { + this->cc_cwnd = this->cc_cwnd + 1/this->cc_cwnd; + } + if (o.debugging > 3) { + log_write(LOG_PLAIN, "[FPNetworkControl] Congestion Control Parameters: cwnd=%f ssthresh=%f sent=%d recv=%d tout=%d outstanding=%d\n", + this->cc_cwnd, this->cc_ssthresh, this->probes_sent, this->responses_recv, this->probes_timedout, + this->probes_sent - this->responses_recv - this->probes_timedout); + } + return OP_SUCCESS; +} + + +/* This method is public and can be called by FPHosts to inform the controller + * that a probe has experienced a final timeout. In other words, that no + * response was received for the probe after doing the necessary retransmissions + * and waiting for the RTO. This is used to decrease the number of outstanding + * probes. Otherwise, if no host responded to the probes, the effective + * transmission window could reach zero and prevent new probes from being sent, + * clogging the engine. */ +int FPNetworkControl::cc_report_final_timeout() { + this->probes_timedout++; + return OP_SUCCESS; +} + + +/* This method is used by FPHosts to request permission to transmit a number of + * probes. Permission is granted if the current congestion window allows the + * transmission of new probes. It returns true if permission is granted and + * false if it is denied. */ +bool FPNetworkControl::request_slots(size_t num_packets) { + int probes_outstanding = this->probes_sent - this->responses_recv - this->probes_timedout; + if (o.debugging > 3) + log_write(LOG_PLAIN, "[FPNetworkControl] Slot request for %u packets. ProbesOutstanding=%d cwnd=%f ssthresh=%f\n", + (unsigned int)num_packets, probes_outstanding, this->cc_cwnd, this->cc_ssthresh); + /* If we still have room for more outstanding probes, let the caller + * schedule transmissions. */ + if ((probes_outstanding + num_packets) <= this->cc_cwnd) { + this->cc_update_sent(num_packets); + return true; + } + return false; +} + + +/* This method lets FPHosts register themselves in the network controller so + * the controller can call them back every time a packet they are interested + * in is captured.*/ +int FPNetworkControl::register_caller(FPHost *newcaller) { + this->callers.push_back(newcaller); + return OP_SUCCESS; +} + + +/* This method lets FPHosts unregister themselves in the network controller so + * the controller does not call them back again. This is called by hosts that + * have already finished their OS detection. */ +int FPNetworkControl::unregister_caller(FPHost *oldcaller) { + for (size_t i = 0; i < this->callers.size(); i++) { + if (this->callers[i] == oldcaller) { + this->callers.erase(this->callers.begin() + i); + return OP_SUCCESS; + } + } + return OP_FAILURE; +} + + +/* This method gets the controller ready for packet capture. Basically it + * obtains a pcap descriptor from nsock and sets an appropriate BPF filter. */ +int FPNetworkControl::setup_sniffer(const char *iface, const char *bpf_filter) { + char *errmsg = NULL; + char pcapdev[128]; + +#ifdef WIN32 + /* Nmap normally uses device names obtained through dnet for interfaces, but + Pcap has its own naming system. So the conversion is done here */ + if (!DnetName2PcapName(iface, pcapdev, sizeof(pcapdev))) { + /* Oh crap -- couldn't find the corresponding dev apparently. Let's just go + with what we have then ... */ + Strncpy(pcapdev, iface, sizeof(pcapdev)); + } +#else + Strncpy(pcapdev, iface, sizeof(pcapdev)); +#endif + + /* Obtain a pcap descriptor */ + if ((errmsg = nsock_pcap_open(this->nsp, this->pcap_nsi, pcapdev, 8192, 0, bpf_filter)) != NULL) + fatal("Error opening capture device %s --> %s\n", pcapdev, errmsg); + + /* Store the pcap NSI inside the pool so we can retrieve it inside a callback */ + nsp_setud(this->nsp, (void *)&(this->pcap_nsi)); + + return OP_SUCCESS; +} + + +/* This method makes the controller process pending events (like packet + * transmissions or packet captures). */ +void FPNetworkControl::handle_events() { + nsock_loop(nsp, 50); +} + + +/* This method lets FPHosts to schedule the transmission of an OS detection + * probe. It takes an FPProbe pointer and the amount of milliseconds the + * controller should wait before injecting the probe into the wire. */ +int FPNetworkControl::scheduleProbe(FPProbe *pkt, int in_msecs_time) { + nsock_timer_create(this->nsp, probe_transmission_handler_wrapper, in_msecs_time, (void*)pkt); + return OP_SUCCESS; +} + + +/* This is the handler for packet transmission. It is called by nsock whenever a timer expires, + * which means that a new packet needs to be transmitted. Note that this method is not + * called directly by Nsock but by the wrapper function probe_transmission_handler_wrapper(). + * The reason for that is because C++ does not allow to use class methods as callback + * functions, so this is a small hack to make that happen. */ +void FPNetworkControl::probe_transmission_handler(nsock_pool nsp, nsock_event nse, void *arg) { + assert(nsp_getud(nsp) != NULL); + nsock_iod nsi_pcap = *((nsock_iod *)nsp_getud(nsp)); + enum nse_status status = nse_status(nse); + enum nse_type type = nse_type(nse); + FPProbe *myprobe = (FPProbe *)arg; + u8 *buf; + size_t len; + + if (status == NSE_STATUS_SUCCESS) { + switch(type) { + /* Timer events mean that we need to send a packet. */ + case NSE_TYPE_TIMER: + + /* The first time a packet is sent, we schedule a pcap event. After that + * we don't have to worry since the response reception handler schedules + * a new capture event for each captured packet. */ + if (!this->first_pcap_scheduled) { + this->pcap_ev_id = nsock_pcap_read_packet(nsp, nsi_pcap, response_reception_handler_wrapper, -1, NULL); + this->first_pcap_scheduled = true; + } + + buf = myprobe->getPacketBuffer(&len); + /* Send the packet*/ + assert(myprobe->host != NULL); + if (send_ip_packet(this->rawsd, myprobe->getEthernet(), myprobe->host->getTargetAddress(), buf, len) == -1) { + pfatal("Unable to send packet in %s", __func__); + } else { + myprobe->setTimeSent(); + } + free(buf); + break; + + default: + fatal("Unexpected Nsock event in probe_transmission_handler()"); + break; + } /* switch(type) */ + } else if (status == NSE_STATUS_EOF) { + if (o.debugging) + log_write(LOG_PLAIN, "probe_transmission_handler(): EOF\n"); + } else if (status == NSE_STATUS_ERROR) { + if (o.debugging) + log_write(LOG_PLAIN, "probe_transmission_handler(): %s failed: %s\n", nse_type2str(type), strerror(socket_errno())); + } else if (status == NSE_STATUS_TIMEOUT) { + if (o.debugging) + log_write(LOG_PLAIN, "probe_transmission_handler(): %s timeout: %s\n", nse_type2str(type), strerror(socket_errno())); + } else if (status == NSE_STATUS_CANCELLED) { + if (o.debugging) + log_write(LOG_PLAIN, "probe_transmission_handler(): %s canceled: %s\n", nse_type2str(type), strerror(socket_errno())); + } else if (status == NSE_STATUS_KILL) { + if (o.debugging) + log_write(LOG_PLAIN, "probe_transmission_handler(): %s killed: %s\n", nse_type2str(type), strerror(socket_errno())); + } else { + if (o.debugging) + log_write(LOG_PLAIN, "probe_transmission_handler(): Unknown status code %d\n", status); + } + return; +} + + +/* This is the handler for packet capture. It is called by nsock whenever libpcap + * captures a packet from the network interface. This method basically captures + * the packet, extracts its source IP address and tries to find an FPHost that + * is targeting such address. If it does, it passes the packet to that FPHost + * via callback() so the FPHost can determine if the packet is actually the + * response to a FPProbe that it sent before. Note that this method is not + * called directly by Nsock but by the wrapper function + * response_reception_handler_wrapper(). See doc in probe_transmission_handler() + * for details. */ +void FPNetworkControl::response_reception_handler(nsock_pool nsp, nsock_event nse, void *arg) { + nsock_iod nsi = nse_iod(nse); + enum nse_status status = nse_status(nse); + enum nse_type type = nse_type(nse); + const u8 *rcvd_pkt = NULL; /* Points to the captured packet */ + size_t rcvd_pkt_len = 0; /* Lenght of the captured packet */ + struct timeval pcaptime; /* Time the packet was captured */ + struct sockaddr_storage sent_ss; + struct sockaddr_storage rcvd_ss; + struct sockaddr_in *rcvd_ss4 = (struct sockaddr_in *)&rcvd_ss; + struct sockaddr_in6 *rcvd_ss6 = (struct sockaddr_in6 *)&rcvd_ss; + memset(&rcvd_ss, 0, sizeof(struct sockaddr_storage)); + IPv4Header ip4; + IPv6Header ip6; + int res = -1; + + struct timeval tv; + gettimeofday(&tv, NULL); + + if (status == NSE_STATUS_SUCCESS) { + switch(type) { + + case NSE_TYPE_PCAP_READ: + + /* Schedule a new pcap read operation */ + this->pcap_ev_id = nsock_pcap_read_packet(nsp, nsi, response_reception_handler_wrapper, -1, NULL); + + /* Get captured packet */ + nse_readpcap(nse, NULL, NULL, &rcvd_pkt, &rcvd_pkt_len, NULL, &pcaptime); + + /* Extract the packet's source address */ + ip4.storeRecvData(rcvd_pkt, rcvd_pkt_len); + if (ip4.validate() != OP_FAILURE && ip4.getVersion() == 4) { + ip4.getSourceAddress(&(rcvd_ss4->sin_addr)); + rcvd_ss4->sin_family = AF_INET; + } else { + ip6.storeRecvData(rcvd_pkt, rcvd_pkt_len); + if (ip6.validate() != OP_FAILURE && ip6.getVersion() == 6) { + ip6.getSourceAddress(&(rcvd_ss6->sin6_addr)); + rcvd_ss6->sin6_family = AF_INET6; + } else { + /* If we get here it means that the received packet is not + * IPv4 or IPv6 so we just discard it returning. */ + return; + } + } + + /* Check if we have a caller that expects packets from this sender */ + for (size_t i = 0; i < this->callers.size(); i++) { + + /* Obtain the target address */ + sent_ss = *this->callers[i]->getTargetAddress(); + + /* Check that the received packet is of the same address family */ + if (sent_ss.ss_family != rcvd_ss.ss_family) + continue; + + /* Check that the captured packet's source address matches the + * target address. If it matches, pass the received packet + * to the appropriate FPHost object through callback(). */ + if (sockaddr_storage_equal(&rcvd_ss, &sent_ss)) { + if ((res = this->callers[i]->callback(rcvd_pkt, rcvd_pkt_len, &tv)) >= 0) { + + /* If callback() returns >=0 it means that the packet we've just + * passed was successfully matched with a previous probe. Now + * update the count of received packets (so we can determine how + * many outstanding packets are out there). Note that we only do + * that if callback() returned >0 because 0 is a special case: a + * reply to a retransmitted timed probe that was already replied + * to in the past. We don't want to count replies to the same probe + * more than once, so that's why we only update when res > 0. */ + if (res > 0) + this->cc_update_received(); + + /* When the callback returns more than 1 it means that the packet + * was sent more than once before being answered. This means that + * we experienced congestion (first transmission got dropped), so + * we update our CC parameters to deal with the congestion. */ + if (res > 1) { + this->cc_report_drop(); + } + } + return; + } + } + break; + + default: + fatal("Unexpected Nsock event in response_reception_handler()"); + break; + + } /* switch(type) */ + + } else if (status == NSE_STATUS_EOF) { + if (o.debugging) + log_write(LOG_PLAIN, "response_reception_handler(): EOF\n"); + } else if (status == NSE_STATUS_ERROR) { + if (o.debugging) + log_write(LOG_PLAIN, "response_reception_handler(): %s failed: %s\n", nse_type2str(type), strerror(socket_errno())); + } else if (status == NSE_STATUS_TIMEOUT) { + if (o.debugging) + log_write(LOG_PLAIN, "response_reception_handler(): %s timeout: %s\n", nse_type2str(type), strerror(socket_errno())); + } else if (status == NSE_STATUS_CANCELLED) { + if (o.debugging) + log_write(LOG_PLAIN, "response_reception_handler(): %s canceled: %s\n", nse_type2str(type), strerror(socket_errno())); + } else if (status == NSE_STATUS_KILL) { + if (o.debugging) + log_write(LOG_PLAIN, "response_reception_handler(): %s killed: %s\n", nse_type2str(type), strerror(socket_errno())); + } else { + if (o.debugging) + log_write(LOG_PLAIN, "response_reception_handler(): Unknown status code %d\n", status); + } + return; +} + + +/****************************************************************************** + * Implementation of class FPEngine. * + ******************************************************************************/ +FPEngine::FPEngine() { + this->osgroup_size = OSSCAN_GROUP_SIZE; +} + + +FPEngine::~FPEngine() { + +} + + +/* Returns a suitable BPF filter for the OS detection. If less than 20 targets + * are passed, the filter contains an explicit list of target addresses. It + * looks similar to this: + * + * dst host fe80::250:56ff:fec0:1 and (src host fe80::20c:29ff:feb0:2316 or src host fe80::20c:29ff:fe9f:5bc2) + * + * When more than 20 targets are passed, a generic filter based on the source + * address is used. The returned filter looks something like: + * + * dst host fe80::250:56ff:fec0:1 + */ +const char *FPEngine::bpf_filter(vector &Targets) { + static char pcap_filter[2048]; + /* 20 IPv6 addresses is max (46 byte addy + 14 (" or src host ")) * 20 == 1200 */ + char dst_hosts[1220]; + int filterlen = 0; + int len = 0; + unsigned int targetno; + memset(pcap_filter, 0, sizeof(pcap_filter)); + + /* If we have 20 or less targets, build a list of addresses so we can set + * an explicit BPF filter */ + if (Targets.size() <= 20) { + for (targetno = 0; targetno < Targets.size(); targetno++) { + len = Snprintf(dst_hosts + filterlen, + sizeof(dst_hosts) - filterlen, + "%ssrc host %s", (targetno == 0)? "" : " or ", + Targets[targetno]->targetipstr()); + + if (len < 0 || len + filterlen >= (int) sizeof(dst_hosts)) + fatal("ran out of space in dst_hosts"); + filterlen += len; + } + if (len < 0 || len + filterlen >= (int) sizeof(dst_hosts)) + fatal("ran out of space in dst_hosts"); + + len = Snprintf(pcap_filter, sizeof(pcap_filter), "dst host %s and (%s)", + Targets[0]->sourceipstr(), dst_hosts); + } else { + len = Snprintf(pcap_filter, sizeof(pcap_filter), "dst host %s", Targets[0]->sourceipstr()); + } + + if (len < 0 || len >= (int) sizeof(pcap_filter)) + fatal("ran out of space in pcap filter"); + + return pcap_filter; +} + + +/****************************************************************************** + * Implementation of class FPEngine6. * + ******************************************************************************/ +FPEngine6::FPEngine6() { + +} + + +FPEngine6::~FPEngine6() { + +} + + +/* From FPmodel.cc. */ +extern struct model FPmodel; +extern double FPscale[][2]; +extern FingerMatch FPmatches[]; + +/* Not all operating systems allow setting the flow label in outgoing packets; + notably all Unixes other than Linux when using raw sockets. This function + finds out whether the flow labels we set are likely really being sent. + Otherwise, the operating system is probably filling in 0. Compare to the + logic in send_ipv6_packet_eth_or_sd. */ +static bool can_set_flow_label(const struct eth_nfo *eth) { + if (eth != NULL) + return true; +#if HAVE_IPV6_IPPROTO_RAW + return true; +#else + return false; +#endif +} + +void FPHost6::fill_FPR(FingerPrintResultsIPv6 *FPR) { + unsigned int i; + + FPR->begin_time = this->begin_time; + + for (i = 0; i < sizeof(this->fp_responses) / sizeof(this->fp_responses[0]); i++) { + const FPResponse *resp; + + resp = this->fp_responses[i]; + if (resp != NULL) { + FPR->fp_responses[i] = new FPResponse(resp->probe_id, resp->buf, resp->len, + resp->senttime, resp->rcvdtime); + } + } + + /* Were we actually able to set the flow label? */ + FPR->flow_label = 0; + for (i = 0; i < sizeof(this->fp_probes) / sizeof(this->fp_probes[0]); i++) { + const FPProbe& probe = fp_probes[0]; + if (probe.is_set()) { + if (can_set_flow_label(probe.getEthernet())) + FPR->flow_label = OSDETECT_FLOW_LABEL; + break; + } + } +} + +static const IPv6Header *find_ipv6(const PacketElement *pe) { + while (pe != NULL && pe->protocol_id() != HEADER_TYPE_IPv6) + pe = pe->getNextElement(); + + return (IPv6Header *) pe; +} + +static const TCPHeader *find_tcp(const PacketElement *pe) { + while (pe != NULL && pe->protocol_id() != HEADER_TYPE_TCP) + pe = pe->getNextElement(); + + return (TCPHeader *) pe; +} + +static double vectorize_plen(const PacketElement *pe) { + const IPv6Header *ipv6; + + ipv6 = find_ipv6(pe); + if (ipv6 == NULL) + return -1; + else + return ipv6->getPayloadLength(); +} + +static double vectorize_tc(const PacketElement *pe) { + const IPv6Header *ipv6; + + ipv6 = find_ipv6(pe); + if (ipv6 == NULL) + return -1; + else + return ipv6->getTrafficClass(); +} + +static double vectorize_isr(std::map& resps) { + const char * const SEQ_PROBE_NAMES[] = {"S1", "S2", "S3", "S4", "S5", "S6"}; + u32 seqs[NELEMS(SEQ_PROBE_NAMES)]; + struct timeval times[NELEMS(SEQ_PROBE_NAMES)]; + unsigned int i, j; + double sum, t; + + j = 0; + for (i = 0; i < NELEMS(SEQ_PROBE_NAMES); i++) { + const char *probe_name; + const FPPacket *fp; + const TCPHeader *tcp; + std::map::iterator it; + + probe_name = SEQ_PROBE_NAMES[i]; + it = resps.find(probe_name); + if (it == resps.end()) + continue; + + fp = &it->second; + tcp = find_tcp(fp->getPacket()); + if (tcp == NULL) + continue; + + seqs[j] = tcp->getSeq(); + times[j] = fp->getTime(); + j++; + } + + if (j < 2) + return -1; + + sum = 0.0; + for (i = 0; i < j - 1; i++) + sum += seqs[i + 1] - seqs[i]; + t = TIMEVAL_FSEC_SUBTRACT(times[j - 1], times[0]); + + return sum / t; +} + +static struct feature_node *vectorize(const FingerPrintResultsIPv6 *FPR) { + const char * const IPV6_PROBE_NAMES[] = {"S1", "S2", "S3", "S4", "S5", "S6", "IE1", "IE2", "NI", "NS", "U1", "TECN", "T2", "T3", "T4", "T5", "T6", "T7"}; + const char * const TCP_PROBE_NAMES[] = {"S1", "S2", "S3", "S4", "S5", "S6", "TECN", "T2", "T3", "T4", "T5", "T6", "T7"}; + unsigned int nr_feature, i, idx; + struct feature_node *features; + std::map resps; + + for (i = 0; i < NUM_FP_PROBES_IPv6; i++) { + PacketElement *pe; + + if (FPR->fp_responses[i] == NULL) + continue; + pe = PacketParser::split(FPR->fp_responses[i]->buf, FPR->fp_responses[i]->len); + assert(pe != NULL); + resps[FPR->fp_responses[i]->probe_id].setPacket(pe); + resps[FPR->fp_responses[i]->probe_id].setTime(&FPR->fp_responses[i]->senttime); + } + + nr_feature = get_nr_feature(&FPmodel); + features = new feature_node[nr_feature + 1]; + for (i = 0; i < nr_feature; i++) { + features[i].index = i + 1; + features[i].value = -1; + } + features[i].index = -1; + + idx = 0; + for (i = 0; i < NELEMS(IPV6_PROBE_NAMES); i++) { + const char *probe_name; + + probe_name = IPV6_PROBE_NAMES[i]; + features[idx++].value = vectorize_plen(resps[probe_name].getPacket()); + features[idx++].value = vectorize_tc(resps[probe_name].getPacket()); + } + /* TCP features */ + features[idx++].value = vectorize_isr(resps); + for (i = 0; i < NELEMS(TCP_PROBE_NAMES); i++) { + const char *probe_name; + const TCPHeader *tcp; + u16 flags; + u16 mask; + unsigned int j; + int mss; + int sackok; + int wscale; + + probe_name = TCP_PROBE_NAMES[i]; + + mss = -1; + sackok = -1; + wscale = -1; + + tcp = find_tcp(resps[probe_name].getPacket()); + if (tcp == NULL) { + /* 48 TCP features. */ + idx += 48; + continue; + } + features[idx++].value = tcp->getWindow(); + flags = tcp->getFlags(); + for (mask = 0x001; mask <= 0x800; mask <<= 1) + features[idx++].value = (flags & mask) != 0; + + for (j = 0; j < 16; j++) { + nping_tcp_opt_t opt; + opt = tcp->getOption(j); + if (opt.value == NULL) + break; + features[idx++].value = opt.type; + /* opt.len includes the two (type, len) bytes. */ + if (opt.type == TCPOPT_MSS && opt.len == 4 && mss == -1) + mss = ntohs(*(u16 *) opt.value); + else if (opt.type == TCPOPT_SACKOK && opt.len == 2 && sackok == -1) + sackok = 1; + else if (opt.type == TCPOPT_WSCALE && opt.len == 3 && wscale == -1) + wscale = *(u8 *) opt.value; + } + for (; j < 16; j++) + idx++; + + for (j = 0; j < 16; j++) { + nping_tcp_opt_t opt; + opt = tcp->getOption(j); + if (opt.value == NULL) + break; + features[idx++].value = opt.len; + } + for (; j < 16; j++) + idx++; + + features[idx++].value = mss; + features[idx++].value = sackok; + features[idx++].value = wscale; + } + assert(idx == nr_feature); + + if (o.debugging > 2) { + log_write(LOG_PLAIN, "v = {"); + for (i = 0; i < nr_feature; i++) + log_write(LOG_PLAIN, "%.16g, ", features[i].value); + log_write(LOG_PLAIN, "};\n"); + } + + return features; +} + +static void apply_scale(struct feature_node *features, unsigned int num_features, + const double (*scale)[2]) { + unsigned int i; + + for (i = 0; i < num_features; i++) { + double val = features[i].value; + if (val < 0) + continue; + val = (val + scale[i][0]) * scale[i][1]; + features[i].value = val; + } +} + +/* (label, prob) pairs for purpose of sorting. */ +struct label_prob { + int label; + double prob; +}; + +int label_prob_cmp(const void *a, const void *b) { + const struct label_prob *la, *lb; + + la = (struct label_prob *) a; + lb = (struct label_prob *) b; + + /* Sort descending. */ + if (la->prob > lb->prob) + return -1; + else if (la->prob < lb->prob) + return 1; + else + return 0; +} + +static void classify(FingerPrintResultsIPv6 *FPR) { + int nr_class, i; + struct feature_node *features; + double *values; + struct label_prob *labels; + + nr_class = get_nr_class(&FPmodel); + + features = vectorize(FPR); + values = new double[nr_class]; + labels = new struct label_prob[nr_class]; + + apply_scale(features, get_nr_feature(&FPmodel), FPscale); + + predict_values(&FPmodel, features, values); + for (i = 0; i < nr_class; i++) { + labels[i].label = i; + labels[i].prob = 1.0 / (1.0 + exp(-values[i])); + } + qsort(labels, nr_class, sizeof(labels[0]), label_prob_cmp); + for (i = 0; i < nr_class && i < MAX_FP_RESULTS; i++) { + FPR->matches[i] = &o.os_labels_ipv6[labels[i].label]; + FPR->accuracy[i] = labels[i].prob; + FPR->num_matches = i + 1; + if (labels[i].prob >= 0.90 * labels[0].prob) + FPR->num_perfect_matches = i + 1; + } + if (o.disable_ipv6_os_results && o.debugging < 2) { + FPR->overall_results = OSSCAN_NOMATCHES; + FPR->num_perfect_matches = 0; + } else if (FPR->num_perfect_matches == 0) { + FPR->overall_results = OSSCAN_NOMATCHES; + } else if (FPR->num_perfect_matches == 1) { + FPR->overall_results = OSSCAN_SUCCESS; + } else { + FPR->overall_results = OSSCAN_NOMATCHES; + FPR->num_perfect_matches = 0; + } + + delete[] features; + delete[] values; + delete[] labels; +} + + +/* This method is the core of the FPEngine class. It takes a list of IPv6 + * targets that need to be fingerprinted. The method handles the whole + * fingerprinting process, sending probes, collecting responses, analyzing + * results and matching fingerprints. If everything goes well, the internal + * state of the supplied target objects will be modified to reflect the results + * of the */ +int FPEngine6::os_scan(vector &Targets) { + bool osscan_done = false; + const char *bpf_filter = NULL; + vector curr_hosts; /* Hosts currently doing OS detection */ + vector done_hosts; /* Hosts for which we already did OSdetect */ + vector left_hosts; /* Hosts we have not yet started with */ + struct timeval begin_time; + + if (o.debugging) + log_write(LOG_PLAIN, "Starting IPv6 OS Scan...\n"); + + /* Initialize variables, timers, etc. */ + gettimeofday(&begin_time, NULL); + global_netctl.init(Targets[0]->deviceName(), Targets[0]->ifType()); + for (size_t i = 0; i < Targets.size(); i++) { + if (o.debugging > 3) { + log_write(LOG_PLAIN, "[FPEngine] Allocating FPHost6 for %s %s\n", + Targets[i]->targetipstr(), Targets[i]->sourceipstr()); + } + FPHost6 *newhost = new FPHost6(Targets[i], &global_netctl); + newhost->begin_time = begin_time; + fphosts.push_back(newhost); + } + + /* Build the BPF filter */ + bpf_filter = this->bpf_filter(Targets); + if (o.debugging) + log_write(LOG_PLAIN, "[FPEngine] Interface=%s BPF:%s\n", Targets[0]->deviceName(), bpf_filter); + + /* Set up the sniffer */ + global_netctl.setup_sniffer(Targets[0]->deviceName(), bpf_filter); + + /* Divide the targets into two groups, the ones we are going to start + * processing, and the ones we leave for later. */ + for (size_t i = 0; i < Targets.size() && i < this->osgroup_size; i++) { + curr_hosts.push_back(fphosts[i]); + } + for (size_t i = curr_hosts.size(); i < Targets.size(); i++) { + left_hosts.push_back(fphosts[i]); + } + + /* Do the OS detection rounds */ + while (!osscan_done) { + osscan_done = true; /* It will remain true only when all hosts are .done() */ + if (o.debugging > 3) { + log_write(LOG_PLAIN, "[FPEngine] CurrHosts=%d, LeftHosts=%d, DoneHosts=%d\n", + (int) curr_hosts.size(), (int) left_hosts.size(), (int) done_hosts.size()); + } + + /* Go through the list of hosts and ask them to schedule their probes */ + for (unsigned int i = 0; i < curr_hosts.size(); i++) { + + /* If the host is not done yet, call shedule() to let it schedule + * new probes, retransmissions, etc. */ + if (!curr_hosts[i]->done()) { + osscan_done = false; + curr_hosts[i]->schedule(); + if (o.debugging > 3) + log_write(LOG_PLAIN, "[FPEngine] CurrHost #%u not done\n", i); + + /* If the host is done, take it out of the curr_hosts group and add it + * to the done_hosts group. If we still have hosts left in the left_hosts + * group, take the first one and insert it into curr_hosts. This way we + * always have a full working group of hosts (unless we ran out of hosts, + * of course). */ + } else { + if (o.debugging > 3) + log_write(LOG_PLAIN, "[FPEngine] CurrHost #%u done\n", i); + if (o.debugging > 3) + log_write(LOG_PLAIN, "[FPEngine] Moving done host %u to the done_hosts list\n", i); + done_hosts.push_back(curr_hosts[i]); + curr_hosts.erase(curr_hosts.begin() + i); + + /* If we still have hosts left, add one to the current group */ + if (left_hosts.size() > 0) { + if (o.debugging > 3) + log_write(LOG_PLAIN, "[FPEngine] Inserting one new hosts in the curr_hosts list.\n"); + curr_hosts.push_back(left_hosts[0]); + left_hosts.erase(left_hosts.begin()); + osscan_done = false; + } + + i--; /* Decrement i so we don't miss the host that is now in the + * position of the host we've just removed from the list */ + } + } + + /* Handle scheduled events */ + global_netctl.handle_events(); + + } + + /* Once we've finished with all fphosts, check which ones were correctly + * fingerprinted, and update the Target objects. */ + for (size_t i = 0; i < this->fphosts.size(); i++) { + fphosts[i]->finish(); + + fphosts[i]->fill_FPR((FingerPrintResultsIPv6 *) Targets[i]->FPR); + classify((FingerPrintResultsIPv6 *) Targets[i]->FPR); + } + + /* Cleanup and return */ + while (this->fphosts.size() > 0) { + FPHost6 *tmp = fphosts.back(); + delete tmp; + fphosts.pop_back(); + } + + if (o.debugging) + log_write(LOG_PLAIN, "IPv6 OS Scan completed.\n"); + return OP_SUCCESS; +} + + +/****************************************************************************** + * Implementation of class FPHost. * + ******************************************************************************/ +FPHost::FPHost() { + this->__reset(); +} + + +FPHost::~FPHost() { + +} + + +void FPHost::__reset() { + this->total_probes = 0; + this->timed_probes = 0; + this->probes_sent = 0; + this->probes_answered = 0; + this->probes_unanswered = 0; + this->detection_done = false; + this->timedprobes_sent = false; + this->target_host = NULL; + this->netctl = NULL; + this->netctl_registered = false; + this->tcpSeqBase = 0; + this->open_port_tcp = -1; + this->closed_port_tcp = -1; + this->closed_port_udp = -1; + this->tcp_port_base = -1; + this->udp_port_base = -1; + /* Retransmission time-out parameters. + * + * From RFC 2988: + * Until a round-trip time (RTT) measurement has been made for a segment + * sent between the sender and receiver, the sender SHOULD set + * RTO <- 3 seconds */ + this->rto = OSSCAN_INITIAL_RTO; + this->rttvar = -1; + this->srtt = -1; + + this->begin_time.tv_sec = 0; + this->begin_time.tv_usec = 0; +} + + +/* Returns the IP address of the target associated with the FPHost in + * stuct sockaddr_storage format. */ +const struct sockaddr_storage *FPHost::getTargetAddress() { + return this->target_host->TargetSockAddr(); +} + + +/* Accesses the Target object associated with the FPHost to extract the port + * numbers to be used in OS detection. In particular it extracts: + * + * - An open TCP port. + * - A closed TCP port. + * - A closed UDP port. + * + * When not enough information is found in the Target, the neccessary port + * numbers are generated randomly. */ +int FPHost::choose_osscan_ports() { + Port *tport = NULL; + Port port; + /* Choose an open TCP port: First, check if the host already has a + * FingerPrintResults object that defines an open port. */ + if (this->target_host->FPR != NULL && this->target_host->FPR->osscan_opentcpport > 0) { + this->open_port_tcp = this->target_host->FPR->osscan_opentcpport; + + /* Otherwise, get the first open port that we've found open */ + } else if ((tport = this->target_host->ports.nextPort(NULL, &port, IPPROTO_TCP, PORT_OPEN))) { + this->open_port_tcp = tport->portno; + /* If it is zero, let's try another one if there is one */ + if (tport->portno == 0) { + if ((tport = this->target_host->ports.nextPort(tport, &port, IPPROTO_TCP, PORT_OPEN))) + this->open_port_tcp = tport->portno; + } + this->target_host->FPR->osscan_opentcpport = this->open_port_tcp; + } else { + /* If we don't have an open port, set it to -1 so we don't send probes that + * target TCP open ports */ + this->open_port_tcp = -1; + } + + /* Choose a closed TCP port. */ + if (this->target_host->FPR != NULL && this->target_host->FPR->osscan_closedtcpport > 0) { + this->closed_port_tcp =this->target_host->FPR->osscan_closedtcpport; + } else if ((tport = this->target_host->ports.nextPort(NULL, &port, IPPROTO_TCP, PORT_CLOSED))) { + this->closed_port_tcp = tport->portno; + /* If it is zero, let's try another one if there is one */ + if (tport->portno == 0) + if ((tport = this->target_host->ports.nextPort(tport, &port, IPPROTO_TCP, PORT_CLOSED))) + this->closed_port_tcp = tport->portno; + this->target_host->FPR->osscan_closedtcpport = this->closed_port_tcp; + } else if ((tport = this->target_host->ports.nextPort(NULL, &port, IPPROTO_TCP, PORT_UNFILTERED))) { + /* Well, we will settle for unfiltered */ + this->closed_port_tcp = tport->portno; + /* But again we'd prefer not to have zero */ + if (tport->portno == 0) + if ((tport =this->target_host->ports.nextPort(tport, &port, IPPROTO_TCP, PORT_UNFILTERED))) + this->closed_port_tcp = tport->portno; + } else { + /* If we don't have a closed port, set it to -1 so we don't send probes that + * target TCP closed ports. */ + this->closed_port_tcp = -1; + } + + /* Closed UDP port */ + if (this->target_host->FPR != NULL && this->target_host->FPR->osscan_closedudpport > 0) { + this->closed_port_udp = this->target_host->FPR->osscan_closedudpport; + } else if ((tport = this->target_host->ports.nextPort(NULL, &port, IPPROTO_UDP, PORT_CLOSED))) { + this->closed_port_udp = tport->portno; + /* Not zero, if possible */ + if (tport->portno == 0) + if ((tport = this->target_host->ports.nextPort(tport, &port, IPPROTO_UDP, PORT_CLOSED))) + this->closed_port_udp = tport->portno; + this->target_host->FPR->osscan_closedudpport = this->closed_port_udp; + } else if ((tport = this->target_host->ports.nextPort(NULL, &port, IPPROTO_UDP, PORT_UNFILTERED))) { + /* Well, we will settle for unfiltered */ + this->closed_port_udp = tport->portno; + /* But not zero, please */ + if (tport->portno == 0) + if ((tport = this->target_host->ports.nextPort(NULL, &port, IPPROTO_UDP, PORT_UNFILTERED))) + this->closed_port_udp = tport->portno; + } else { + /* Pick one at random. Shrug. */ + this->closed_port_udp = (get_random_uint() % 14781) + 30000; + } + + this->tcpSeqBase = get_random_u32(); + this->tcp_port_base = o.magic_port_set ? o.magic_port : o.magic_port + get_random_u8(); + this->udp_port_base = o.magic_port_set ? o.magic_port : o.magic_port + get_random_u8(); + this->icmp_seq_counter = 0; + + return OP_SUCCESS; +} + + +/* This method is called whenever we receive a response to a probe. It + * recomputes the host's retransmission timer based on the new RTT measure. + * @param measured_rtt_usecs is the new RTT observation in MICROseconds. + * @param retransmission indicates whether the observed RTT correspond to + * a packet that was transmitted more than once or not. It is used to + * avoid using RTT samples obtained from retransmissions (Karn's algorithm) */ +int FPHost::update_RTO(int measured_rtt_usecs, bool retransmission) { +/* RFC 2988: TCP MUST use Karn's algorithm [KP87] for taking RTT samples. That + * is, RTT samples MUST NOT be made using segments that were + * retransmitted (and thus for which it is ambiguous whether the reply + * was for the first instance of the packet or a later instance).*/ + if (retransmission == true) + return OP_SUCCESS; + +/* RFC 2988: When the first RTT measurement R is made, the host MUST set + * + * SRTT <- R + * RTTVAR <- R/2 + * RTO <- SRTT + max (G, K*RTTVAR) + * + * where K = 4, and G is the clock granularity.. */ + if (this->srtt == -1 && this->rttvar == -1) { + this->srtt = measured_rtt_usecs; + this->rttvar = measured_rtt_usecs/2; + this->rto = this->srtt + MAX(500000, 4*this->rttvar); /* Asume a granularity of 1/2 sec */ + } else { + + /* RFC 2988: When a subsequent RTT measurement R' is made, a host MUST set + * + * RTTVAR <- (1 - beta) * RTTVAR + beta * |SRTT - R'| + * SRTT <- (1 - alpha) * SRTT + alpha * R' + * + * The above SHOULD be computed using alpha = 1/8 and beta = 1/4. + * After the computation, a host MUST update + * + * RTO <- SRTT + max (G, K*RTTVAR) + */ + this->rttvar = ((1.0 - 0.25) * this->rttvar) + (0.25 * ABS(this->srtt - measured_rtt_usecs)); + this->srtt = ((1.0 - 0.125) * this->srtt) + (0.125 * measured_rtt_usecs); + this->rto = this->srtt + MAX(500000, 4*this->rttvar); + } + +/* RFC 2988: Whenever RTO is computed, if it is less than 1 second then the RTO + * SHOULD be rounded up to 1 second. + * [NOTE: In Nmap we find this excessive, so we set a minimum of 100ms + * (100,000 usecs). It may seem aggressive but waiting too long can cause + * the engine to fail to detect drops until many probes later on extremely + * low-latency networks (such as localhost scans). */ + if (this->rto < (MIN_RTT_TIMEOUT*1000)) + this->rto = (MIN_RTT_TIMEOUT*1000); + return this->rto; +} + + +/****************************************************************************** + * Implementation of class FPHost6. * + ******************************************************************************/ + +FPHost6::FPHost6(Target *tgt, FPNetworkControl *fpnc) { + this->init(tgt, fpnc); + return; +} + + +FPHost6::~FPHost6() { + this->reset(); +} + + +void FPHost6::reset() { + this->__reset(); + for (unsigned int i = 0; i < NUM_FP_PROBES_IPv6; i++) { + this->fp_probes[i].reset(); + if (this->fp_responses[i]) { + delete this->fp_responses[i]; + this->fp_responses[i] = NULL; + } + } +} + + +void FPHost6::init(Target *tgt, FPNetworkControl *fpnc) { + this->target_host = tgt; + this->netctl = fpnc; + this->total_probes = 0; + this->timed_probes = 0; + + /* Set state in the supplied Target */ + if (this->target_host->FPR == NULL) + this->target_host->FPR = new FingerPrintResultsIPv6; + this->target_host->osscanSetFlag(OS_PERF); + + /* Choose TCP/UDP ports for the prbes. */ + this->choose_osscan_ports(); + + /* Build the list of OS detection probes */ + this->build_probe_list(); + + for (unsigned int i = 0; i < NUM_FP_PROBES_IPv6; i++) + this->fp_responses[i] = NULL; + + for (unsigned int i = 0; i < NUM_FP_TIMEDPROBES_IPv6; i++) + this->aux_resp[i] = NULL; +} + +/* Get the hop limit encapsulated in an ICMPv6 error reply. Return -1 if it + * can't be found. */ +static int get_encapsulated_hoplimit(const PacketElement *pe) { + /* Check that it's IPv6. */ + if (pe == NULL || pe->protocol_id() != HEADER_TYPE_IPv6) + return -1; + /* Find the ICMPv6 payload. */ + pe = pe->getNextElement(); + for (; pe != NULL; pe = pe->getNextElement()) { + if (pe->protocol_id() == HEADER_TYPE_ICMPv6) + break; + } + if (pe == NULL) + return -1; + /* Check that encapsulated is IPv6. */ + pe = pe->getNextElement(); + if (pe == NULL || pe->protocol_id() != HEADER_TYPE_IPv6) + return -1; + + return ((IPv6Header *) pe)->getHopLimit(); +} + +void FPHost6::finish() { + /* These probes are likely to get an ICMPv6 error (allowing us to calculate + distance. */ + const char * const DISTANCE_PROBE_NAMES[] = { "IE2", "NI", "U1" }; + int distance = -1; + int hoplimit_distance = -1; + enum dist_calc_method distance_calculation_method = DIST_METHOD_NONE; + unsigned int i; + + /* Calculate distance based on hop limit difference. */ + for (i = 0; i < NELEMS(DISTANCE_PROBE_NAMES); i++) { + const FPProbe *probe; + const FPResponse *resp; + const PacketElement *probe_pe; + PacketElement *resp_pe; + int sent_ttl, rcvd_ttl; + const char *probe_name; + + probe_name = DISTANCE_PROBE_NAMES[i]; + probe = this->getProbe(probe_name); + resp = this->getResponse(probe_name); + if (probe == NULL || resp == NULL) + continue; + probe_pe = probe->getPacket(); + if (probe_pe->protocol_id() != HEADER_TYPE_IPv6) + continue; + sent_ttl = ((IPv6Header *) probe_pe)->getHopLimit(); + + resp_pe = PacketParser::split(resp->buf, resp->len); + assert(resp_pe != NULL); + rcvd_ttl = get_encapsulated_hoplimit(resp_pe); + if (rcvd_ttl != -1) { + if (o.debugging > 1) { + log_write(LOG_PLAIN, "Hop limit distance from %s probe: %d - %d + 1 == %d\n", + probe_name, sent_ttl, rcvd_ttl, sent_ttl - rcvd_ttl + 1); + } + /* Set only if not already set. */ + if (hoplimit_distance == -1) + hoplimit_distance = sent_ttl - rcvd_ttl + 1; + + /* Special case: for the U1 probe, mark that we found the port closed. */ + if (this->target_host->FPR->osscan_closedudpport == -1 && strcmp(probe_name, "U1") == 0) { + const PacketElement *udp; + u16 portno; + + udp = probe_pe->getNextElement(); + assert(udp != NULL); + assert(udp->protocol_id() == HEADER_TYPE_UDP); + portno = ((UDPHeader *) udp)->getDestinationPort(); + this->target_host->FPR->osscan_closedudpport = portno; + } + } + PacketParser::freePacketChain(resp_pe); + } + + if (islocalhost(this->target_host->TargetSockAddr())) { + /* scanning localhost */ + distance = 0; + distance_calculation_method = DIST_METHOD_LOCALHOST; + } else if (this->target_host->directlyConnected()) { + /* on the same network segment */ + distance = 1; + distance_calculation_method = DIST_METHOD_DIRECT; + } else if (hoplimit_distance != -1) { + distance = hoplimit_distance; + distance_calculation_method = DIST_METHOD_ICMP; + } + + this->target_host->distance = this->target_host->FPR->distance = distance; + this->target_host->distance_calculation_method = distance_calculation_method; +} + +struct tcp_desc { + const char *id; + u16 win; + u8 flags; + u16 dstport; + u16 urgptr; + const char *opts; + unsigned int optslen; +}; + +static u8 get_hoplimit() { + if (o.ttl != -1) + return o.ttl; + else + return (get_random_uint() % 23) + 37; +} + +static IPv6Header *make_tcp(const struct sockaddr_in6 *src, + const struct sockaddr_in6 *dst, + u32 fl, u16 win, u32 seq, u32 ack, u8 flags, u16 srcport, u16 dstport, + u16 urgptr, const char *opts, unsigned int optslen) { + IPv6Header *ip6; + TCPHeader *tcp; + + /* Allocate an instance of the protocol headers */ + ip6 = new IPv6Header(); + tcp = new TCPHeader(); + + ip6->setSourceAddress(src->sin6_addr); + ip6->setDestinationAddress(dst->sin6_addr); + + ip6->setFlowLabel(fl); + ip6->setHopLimit(get_hoplimit()); + ip6->setNextHeader("TCP"); + ip6->setNextElement(tcp); + + tcp->setWindow(win); + tcp->setSeq(seq); + tcp->setAck(ack); + tcp->setFlags(flags); + tcp->setSourcePort(srcport); + tcp->setDestinationPort(dstport); + tcp->setUrgPointer(urgptr); + tcp->setOptions((u8 *) opts, optslen); + + ip6->setPayloadLength(tcp->getLen()); + tcp->setSum(); + + return ip6; +} + +/* This method generates the list of OS detection probes to be sent to the + * target. It also sets up the list of responses. It is defined private + * because it is called by the constructor when the class is instantiated. */ +int FPHost6::build_probe_list() { +#define OPEN 1 +#define CLSD 0 + /* TCP Options: + * S1-S6: six sequencing probes. + * TECN: ECN probe. + * T2-T7: other non-sequencing probes. + * + * option 0: WScale (10), Nop, MSS (1460), Timestamp, SackP + * option 1: MSS (1400), WScale (0), SackP, T(0xFFFFFFFF,0x0), EOL + * option 2: T(0xFFFFFFFF, 0x0), Nop, Nop, WScale (5), Nop, MSS (640) + * option 3: SackP, T(0xFFFFFFFF,0x0), WScale (10), EOL + * option 4: MSS (536), SackP, T(0xFFFFFFFF,0x0), WScale (10), EOL + * option 5: MSS (265), SackP, T(0xFFFFFFFF,0x0) + * option 6: WScale (10), Nop, MSS (1460), SackP, Nop, Nop + * option 7-11: WScale (10), Nop, MSS (265), T(0xFFFFFFFF,0x0), SackP + * option 12: WScale (15), Nop, MSS (265), T(0xFFFFFFFF,0x0), SackP */ + const struct tcp_desc TCP_DESCS[] = { + { "S1", 1, 0x02, OPEN, 0, + "\x03\x03\x0A\x01\x02\x04\x05\xb4\x08\x0A\xff\xff\xff\xff\x00\x00\x00\x00\x04\x02", 20 }, + { "S2", 63, 0x02, OPEN, 0, + "\x02\x04\x05\x78\x03\x03\x00\x04\x02\x08\x0A\xff\xff\xff\xff\x00\x00\x00\x00\x00", 20 }, + { "S3", 4, 0x02, OPEN, 0, + "\x08\x0A\xff\xff\xff\xff\x00\x00\x00\x00\x01\x01\x03\x03\x05\x01\x02\x04\x02\x80", 20 }, + { "S4", 4, 0x02, OPEN, 0, + "\x04\x02\x08\x0A\xff\xff\xff\xff\x00\x00\x00\x00\x03\x03\x0A\x00", 16 }, + { "S5", 16, 0x02, OPEN, 0, + "\x02\x04\x02\x18\x04\x02\x08\x0A\xff\xff\xff\xff\x00\x00\x00\x00\x03\x03\x0A\x00", 20 }, + { "S6", 512, 0x02, OPEN, 0, + "\x02\x04\x01\x09\x04\x02\x08\x0A\xff\xff\xff\xff\x00\x00\x00\x00", 16 }, + { "TECN", 3, 0xc2, OPEN, 63477, + "\x03\x03\x0A\x01\x02\x04\x05\xb4\x04\x02\x01\x01", 12 }, + { "T2", 128, 0x00, OPEN, 0, + "\x03\x03\x0A\x01\x02\x04\x01\x09\x08\x0A\xff\xff\xff\xff\x00\x00\x00\x00\x04\x02", 20 }, + { "T3", 256, 0x2b, OPEN, 0, + "\x03\x03\x0A\x01\x02\x04\x01\x09\x08\x0A\xff\xff\xff\xff\x00\x00\x00\x00\x04\x02", 20 }, + { "T4", 1024, 0x10, OPEN, 0, + "\x03\x03\x0A\x01\x02\x04\x01\x09\x08\x0A\xff\xff\xff\xff\x00\x00\x00\x00\x04\x02", 20 }, + { "T5", 31337, 0x02, CLSD, 0, + "\x03\x03\x0A\x01\x02\x04\x01\x09\x08\x0A\xff\xff\xff\xff\x00\x00\x00\x00\x04\x02", 20 }, + { "T6", 32768, 0x10, CLSD, 0, + "\x03\x03\x0A\x01\x02\x04\x01\x09\x08\x0A\xff\xff\xff\xff\x00\x00\x00\x00\x04\x02", 20 }, + { "T7", 65535, 0x29, CLSD, 0, + "\x03\x03\x0f\x01\x02\x04\x01\x09\x08\x0A\xff\xff\xff\xff\x00\x00\x00\x00\x04\x02", 20 }, + }; + + sockaddr_storage ss; + size_t slen = 0; + sockaddr_in6 *ss6 = (sockaddr_in6 *)&ss; + IPv6Header *ip6; + ICMPv6Header *icmp6; + UDPHeader *udp; + DestOptsHeader *dstopts; + RoutingHeader *routing; + HopByHopHeader *hopbyhop1, *hopbyhop2; + RawData *payload; + unsigned int i; + char payloadbuf[300]; + + assert(this->target_host != NULL); + + /* Set timed TCP probes */ + for (i = 0; i < NUM_FP_PROBES_IPv6_TCP && i < NUM_FP_TIMEDPROBES_IPv6; i++) { + /* If the probe is targeted to a TCP port and we don't have + * any port number for that particular state, skip the probe. */ + if (TCP_DESCS[i].dstport == OPEN && this->open_port_tcp < 0) + continue; + if (TCP_DESCS[i].dstport == CLSD && this->closed_port_tcp < 0) + continue; + + ip6 = make_tcp((struct sockaddr_in6 *) this->target_host->SourceSockAddr(), + (struct sockaddr_in6 *) this->target_host->TargetSockAddr(), + OSDETECT_FLOW_LABEL, TCP_DESCS[i].win, this->tcpSeqBase + i, get_random_u32(), + TCP_DESCS[i].flags, this->tcp_port_base + i, + TCP_DESCS[i].dstport == OPEN ? this->open_port_tcp : this->closed_port_tcp, + TCP_DESCS[i].urgptr, TCP_DESCS[i].opts, TCP_DESCS[i].optslen); + + /* Store the probe in the list so we can send it later */ + this->fp_probes[this->total_probes].host = this; + this->fp_probes[this->total_probes].setPacket(ip6); + this->fp_probes[this->total_probes].setProbeID(TCP_DESCS[i].id); + this->fp_probes[this->total_probes].setEthernet(this->target_host->SrcMACAddress(), this->target_host->NextHopMACAddress(), this->target_host->deviceName()); + /* Mark as a timed probe. */ + this->fp_probes[this->total_probes].setTimed(); + this->timed_probes++; + this->total_probes++; + } + + + /* Set ICMPv6 probes */ + + memset(payloadbuf, 0, 120); + + /* ICMP Probe #1: Echo Request with hop-by-hop options */ + /* This one immediately follows the timed seq TCP probes, to allow testing for + shared flow label sequence. */ + ip6 = new IPv6Header(); + icmp6 = new ICMPv6Header(); + hopbyhop1 = new HopByHopHeader(); + payload = new RawData(); + this->target_host->SourceSockAddr(&ss, &slen); + ip6->setSourceAddress(ss6->sin6_addr); + this->target_host->TargetSockAddr(&ss, &slen); + ip6->setDestinationAddress(ss6->sin6_addr); + ip6->setFlowLabel(OSDETECT_FLOW_LABEL); + ip6->setHopLimit(get_hoplimit()); + ip6->setNextHeader((u8) HEADER_TYPE_IPv6_HOPOPT); + ip6->setNextElement(hopbyhop1); + hopbyhop1->setNextHeader(HEADER_TYPE_ICMPv6); + hopbyhop1->setNextElement(icmp6); + icmp6->setNextElement(payload); + payload->store((u8 *) payloadbuf, 120); + icmp6->setType(ICMPv6_ECHO); + icmp6->setCode(9); // But is supposed to be 0. + icmp6->setIdentifier(0xabcd); + icmp6->setSequence(this->icmp_seq_counter++); + icmp6->setTargetAddress(ss6->sin6_addr); // Should still contain target's addr + ip6->setPayloadLength(); + icmp6->setSum(); + this->fp_probes[this->total_probes].host = this; + this->fp_probes[this->total_probes].setPacket(ip6); + this->fp_probes[this->total_probes].setProbeID("IE1"); + this->fp_probes[this->total_probes].setEthernet(this->target_host->SrcMACAddress(), this->target_host->NextHopMACAddress(), this->target_host->deviceName()); + this->total_probes++; + + /* ICMP Probe #2: Echo Request with badly ordered extension headers */ + ip6 = new IPv6Header(); + hopbyhop1 = new HopByHopHeader(); + dstopts = new DestOptsHeader(); + routing = new RoutingHeader(); + hopbyhop2 = new HopByHopHeader(); + icmp6 = new ICMPv6Header(); + this->target_host->SourceSockAddr(&ss, &slen); + ip6->setSourceAddress(ss6->sin6_addr); + this->target_host->TargetSockAddr(&ss, &slen); + ip6->setDestinationAddress(ss6->sin6_addr); + ip6->setFlowLabel(OSDETECT_FLOW_LABEL); + ip6->setHopLimit(get_hoplimit()); + ip6->setNextHeader((u8) HEADER_TYPE_IPv6_HOPOPT); + ip6->setNextElement(hopbyhop1); + hopbyhop1->setNextHeader(HEADER_TYPE_IPv6_OPTS); + hopbyhop1->setNextElement(dstopts); + dstopts->setNextHeader(HEADER_TYPE_IPv6_ROUTE); + dstopts->setNextElement(routing); + routing->setNextHeader(HEADER_TYPE_IPv6_HOPOPT); + routing->setNextElement(hopbyhop2); + hopbyhop2->setNextHeader(HEADER_TYPE_ICMPv6); + hopbyhop2->setNextElement(icmp6); + icmp6->setType(ICMPv6_ECHO); + icmp6->setCode(0); + icmp6->setIdentifier(0xabcd); + icmp6->setSequence(this->icmp_seq_counter++); + icmp6->setTargetAddress(ss6->sin6_addr); // Should still contain target's addr + ip6->setPayloadLength(); + icmp6->setSum(); + this->fp_probes[this->total_probes].host = this; + this->fp_probes[this->total_probes].setPacket(ip6); + this->fp_probes[this->total_probes].setProbeID("IE2"); + this->fp_probes[this->total_probes].setEthernet(this->target_host->SrcMACAddress(), this->target_host->NextHopMACAddress(), this->target_host->deviceName()); + this->total_probes++; + + /* ICMP Probe #3: Node Info Query (IPv4 addresses) */ + ip6 = new IPv6Header(); + icmp6 = new ICMPv6Header(); + this->target_host->SourceSockAddr(&ss, &slen); + ip6->setSourceAddress(ss6->sin6_addr); + this->target_host->TargetSockAddr(&ss, &slen); + ip6->setDestinationAddress(ss6->sin6_addr); + ip6->setFlowLabel(OSDETECT_FLOW_LABEL); + ip6->setHopLimit(get_hoplimit()); + ip6->setNextHeader("ICMPv6"); + ip6->setNextElement(icmp6); + icmp6->setType(ICMPv6_NODEINFOQUERY); + icmp6->setCode(ICMPv6_NODEINFOQUERY_IPv6ADDR); + icmp6->setTargetAddress(ss6->sin6_addr); // Should still contain target's addr + icmp6->setQtype(NI_QTYPE_IPv4ADDRS); + icmp6->setA(); + icmp6->setNonce((u8 *) "\x01\x02\x03\x04\x05\x06\x07\x0a"); + icmp6->setSum(); + ip6->setPayloadLength(); + this->fp_probes[this->total_probes].host = this; + this->fp_probes[this->total_probes].setPacket(ip6); + this->fp_probes[this->total_probes].setProbeID("NI"); + this->fp_probes[this->total_probes].setEthernet(this->target_host->SrcMACAddress(), this->target_host->NextHopMACAddress(), this->target_host->deviceName()); + this->total_probes++; + + /* ICMP Probe #4: Neighbor Solicitation. (only sent to on-link targets) */ + if (this->target_host->directlyConnected()) { + ip6 = new IPv6Header(); + icmp6 = new ICMPv6Header(); + this->target_host->SourceSockAddr(&ss, &slen); + ip6->setSourceAddress(ss6->sin6_addr); + this->target_host->TargetSockAddr(&ss, &slen); + ip6->setDestinationAddress(ss6->sin6_addr); + ip6->setFlowLabel(OSDETECT_FLOW_LABEL); + /* RFC 2461 section 7.1.1: "A node MUST silently discard any received + Neighbor Solicitation messages that do not satisfy all of the following + validity checks: - The IP Hop Limit field has a value of 255 ... */ + ip6->setHopLimit(255); + ip6->setNextHeader("ICMPv6"); + ip6->setNextElement(icmp6); + icmp6->setType(ICMPv6_NGHBRSOLICIT); + icmp6->setCode(0); + icmp6->setTargetAddress(ss6->sin6_addr); // Should still contain target's addr + icmp6->setSum(); + ip6->setPayloadLength(); + this->fp_probes[this->total_probes].host = this; + this->fp_probes[this->total_probes].setPacket(ip6); + this->fp_probes[this->total_probes].setProbeID("NS"); + this->fp_probes[this->total_probes].setEthernet(this->target_host->SrcMACAddress(), this->target_host->NextHopMACAddress(), this->target_host->deviceName()); + this->total_probes++; + } + + /* Set UDP probes */ + + memset(payloadbuf, 0x43, 300); + + ip6 = new IPv6Header(); + udp = new UDPHeader(); + payload = new RawData(); + this->target_host->SourceSockAddr(&ss, &slen); + ip6->setSourceAddress(ss6->sin6_addr); + this->target_host->TargetSockAddr(&ss, &slen); + ip6->setDestinationAddress(ss6->sin6_addr); + ip6->setFlowLabel(OSDETECT_FLOW_LABEL); + ip6->setHopLimit(get_hoplimit()); + ip6->setNextHeader("UDP"); + ip6->setNextElement(udp); + udp->setSourcePort(this->udp_port_base); + udp->setDestinationPort(this->closed_port_udp); + payload->store((u8 *) payloadbuf, 300); + udp->setNextElement(payload); + udp->setTotalLength(); + udp->setSum(); + ip6->setPayloadLength(udp->getLen()); + this->fp_probes[this->total_probes].host = this; + this->fp_probes[this->total_probes].setPacket(ip6); + this->fp_probes[this->total_probes].setProbeID("U1"); + this->fp_probes[this->total_probes].setEthernet(this->target_host->SrcMACAddress(), this->target_host->NextHopMACAddress(), this->target_host->deviceName()); + this->total_probes++; + + /* Set TECN probe */ + if ((TCP_DESCS[i].dstport == OPEN && this->open_port_tcp >= 0) + || (TCP_DESCS[i].dstport == CLSD && this->closed_port_tcp >= 0)) { + ip6 = make_tcp((struct sockaddr_in6 *) this->target_host->SourceSockAddr(), + (struct sockaddr_in6 *) this->target_host->TargetSockAddr(), + OSDETECT_FLOW_LABEL, TCP_DESCS[i].win, this->tcpSeqBase + i, 0, + TCP_DESCS[i].flags, tcp_port_base + i, + TCP_DESCS[i].dstport == OPEN ? this->open_port_tcp : this->closed_port_tcp, + TCP_DESCS[i].urgptr, TCP_DESCS[i].opts, TCP_DESCS[i].optslen); + + /* Store the probe in the list so we can send it later */ + this->fp_probes[this->total_probes].host = this; + this->fp_probes[this->total_probes].setPacket(ip6); + this->fp_probes[this->total_probes].setProbeID(TCP_DESCS[i].id); + this->fp_probes[this->total_probes].setEthernet(this->target_host->SrcMACAddress(), this->target_host->NextHopMACAddress(), this->target_host->deviceName()); + this->total_probes++; + } + i++; + + /* Set untimed TCP probes */ + for ( ; i < NUM_FP_PROBES_IPv6_TCP; i++) { + /* If the probe is targeted to a TCP port and we don't have + * any port number for that particular state, skip the probe. */ + if (TCP_DESCS[i].dstport == OPEN && this->open_port_tcp < 0) + continue; + if (TCP_DESCS[i].dstport == CLSD && this->closed_port_tcp < 0) + continue; + + ip6 = make_tcp((struct sockaddr_in6 *) this->target_host->SourceSockAddr(), + (struct sockaddr_in6 *) this->target_host->TargetSockAddr(), + OSDETECT_FLOW_LABEL, TCP_DESCS[i].win, this->tcpSeqBase + i, get_random_u32(), + TCP_DESCS[i].flags, tcp_port_base + i, + TCP_DESCS[i].dstport == OPEN ? this->open_port_tcp : this->closed_port_tcp, + TCP_DESCS[i].urgptr, TCP_DESCS[i].opts, TCP_DESCS[i].optslen); + + /* Store the probe in the list so we can send it later */ + this->fp_probes[this->total_probes].host = this; + this->fp_probes[this->total_probes].setPacket(ip6); + this->fp_probes[this->total_probes].setProbeID(TCP_DESCS[i].id); + this->fp_probes[this->total_probes].setEthernet(this->target_host->SrcMACAddress(), this->target_host->NextHopMACAddress(), this->target_host->deviceName()); + this->total_probes++; + } + + return OP_SUCCESS; +} + +/* Indicates whether the OS detection process has finished for this host. + * Note that when "true" is returned the caller cannot assume that the host + * has been accurately fingerprinted, only that the OS detection process + * was carried out. In other words, when true is returned it means that the + * fingerprinting engine sent all OS detection probes, performed the necessary + * retransmission and attempted to capture the target's replies. In order to + * check if the detection was successful (if we actually know what OS the target + * is running), the status() method should be used. */ +bool FPHost6::done() { + if (this->probes_sent == this->total_probes) { + if (this->probes_answered + this->probes_unanswered == this->total_probes) + return true; + } + return false; +} + + +/* Asks the host to schedule the transmission of probes (if they need to do so). + * This method is called repeatedly by the FPEngine to make the host request + * the probe transmissions that it needs. From the hosts point of view, it + * determines if new transmissions need to be scheduled based on the number + * of probes sent, the number of answers received, etc. Also, in order to + * transmit a packet, the network controller must approve it (hosts may not + * be able to send packets any time they want due to congestion control + * restrictions). */ +int FPHost6::schedule() { + struct timeval now; + unsigned int timed_probes_answered = 0; + unsigned int timed_probes_timedout = 0; + + /* The first time we are asked to schedule a packet, register ourselves in + * the network controller so it can call us back when packets that match our + * target are captured. */ + if (this->netctl_registered == false && this->netctl != NULL) { + this->netctl->register_caller(this); + this->netctl_registered = true; + } + + /* Make sure we have things to do, otherwise, just return. */ + if (this->detection_done || (this->probes_answered + this->probes_unanswered == this->total_probes)) { + /* Update our internal state to indicate we have finished */ + if (!this->detection_done) + this->set_done_and_wrap_up(); + return OP_SUCCESS; + } + + /* If we have not yet sent the timed probes (and we have timed probes to send) + * request permission from the network controller and schedule the transmission + * for all of them, 100ms apart from each other. We don't want all the hosts + * to schedule their transmission for the same exact time so we add a random + * offset (between 0 and 100ms) to the first transmission. All subsequent + * ones are sent 100ms apart from the first. Note that if we did not find + * and open port, then we just don't send the timed probes. */ + if (this->timed_probes > 0 && this->timedprobes_sent == false) { + if (o.debugging > 3) + log_write(LOG_PLAIN, "[%s] %u Tx slots requested\n", this->target_host->targetipstr(), this->timed_probes); + if (this->netctl->request_slots(this->timed_probes) == true) { + if (o.debugging > 3) + log_write(LOG_PLAIN, "[%s] Slots granted!\n", this->target_host->targetipstr()); + this->timedprobes_sent = true; + int whentostart = get_random_u8()%100; + for (size_t i = 0; i < this->timed_probes; i++) { + this->netctl->scheduleProbe(&(this->fp_probes[i]), whentostart + i*100); + this->probes_sent++; + } + return OP_SUCCESS; + } + if (o.debugging > 3) + log_write(LOG_PLAIN, "[%s] Slots denied.\n", this->target_host->targetipstr()); + return OP_FAILURE; + } else if (this->timed_probes > 0 && this->timedprobes_sent && this->fp_probes[this->timed_probes - 1].getTimeSent().tv_sec == 0) { + /* If the sent time for the last timed probe has not been set, it means + * that we haven't sent all the timed probes yet, so we don't schedule + * any other probes, we just wait until our schedule() gets called again. + * We do this because we don't want to mess with the target's stack + * in the middle of our timed probes. Otherwise, we can screw up the + * TCP sequence generation tests, etc. We also get here when timed probes + * suffer a retransmission. In that case, we also stop sending packets + * to our target until we have sent all of them. */ + if (o.debugging > 3) + log_write(LOG_PLAIN, "[%s] Waiting for all timed probes to be sent...\n", this->target_host->targetipstr()); + return OP_FAILURE; + } else { + /* If we get here it means that either we have sent all the timed probes or + * we don't even have to send them (because no open port was found). + * At this point if we have other probes to transmit, schedule the next one. + * Also, check for timedout probes so we can retransmit one of them. */ + if (o.debugging > 3 && this->timed_probes > 0 && this->probes_sent == this->timed_probes) + log_write(LOG_PLAIN, "[%s] All timed probes have been sent.\n", this->target_host->targetipstr()); + + if (this->probes_sent < this->total_probes) { + if (this->netctl->request_slots(1) == true) { + if (o.debugging > 3) + log_write(LOG_PLAIN, "[%s] Scheduling probe %s\n", this->target_host->targetipstr(), this->fp_probes[this->probes_sent].getProbeID()); + this->netctl->scheduleProbe(&(this->fp_probes[this->probes_sent]), 0); + this->probes_sent++; + } else { + if (o.debugging > 3) + log_write(LOG_PLAIN, "[%s] Can't schedule probe %s\n", this->target_host->targetipstr(), this->fp_probes[this->probes_sent].getProbeID()); + } + } + + /************************************************************************** + * PROBE TIMEOUT HANDLING * + **************************************************************************/ + if (o.debugging > 3) + log_write(LOG_PLAIN, "[%s] Checking for regular probe timeouts...\n", this->target_host->targetipstr()); + + /* Determine if some regular probe (not timed probes) has timedout. In that + * case, choose some outstanding probe to retransmit. */ + gettimeofday(&now, NULL); + for (unsigned int i = this->timed_probes; i < this->probes_sent; i++) { + + /* Skip probes that have already been answered */ + if (this->fp_responses[i]) { + continue; + } + + /* Skip probes that we have scheduled but have not been yet transmitted */ + if (this->fp_probes[i].getTimeSent().tv_sec == 0) + continue; + + /* Skip probes for which we didn't get a response after all + * retransmissions. */ + if (this->fp_probes[i].probeFailed()) { + continue; + } + + /* Check if the probe timedout */ + if (TIMEVAL_SUBTRACT(now, this->fp_probes[i].getTimeSent()) >= this->rto) { + + /* If we have reached the maximum number of retransmissions, mark the + * probe as failed. Otherwise, schedule its transmission. */ + if (this->fp_probes[i].getRetransmissions() >= o.maxOSTries()) { + if (o.debugging > 3) { + log_write(LOG_PLAIN, "[%s] Probe #%d (%s) failed after %d retransmissions.\n", + this->target_host->targetipstr(), i, this->fp_probes[i].getProbeID(), + this->fp_probes[i].getRetransmissions()); + } + this->fp_probes[i].setFailed(); + /* Let the network controller know that we don't expect a response + * for the probe anymore so the number of outstanding probes is + * reduced and the effective window is incremented. */ + this->netctl->cc_report_final_timeout(); + /* Also, increase our unanswered counter so we can later decide + * if the process has finished. */ + this->probes_unanswered++; + continue; + /* Otherwise, retransmit the packet.*/ + } else { + /* Note that we do not request permission to re-transmit (we don't + * call request_slots(). In TCP one can retransmit timedout + * probes even when CWND is zero, as CWND only applies for new packets. */ + if (o.debugging > 3) { + log_write(LOG_PLAIN, "[%s] Retransmitting probe #%d (%s) (retransmitted %d times already).\n", + this->target_host->targetipstr(), i, this->fp_probes[i].getProbeID(), + this->fp_probes[i].getRetransmissions()); + } + this->fp_probes[i].incrementRetransmissions(); + this->fp_probes[i].resetTimeSent(); + this->netctl->scheduleProbe(&(this->fp_probes[i]), 0); + break; + } + } + } + + /* Now let's check the state of the timed probes. We iterate over the list + * of timed probes to count how many have been answered and how many have + * timed out. If answered + timeout == total_timed_probes, it's time to + * retransmit them. */ + + /* Make sure we are actually sending timed probes. */ + if (this->timed_probes <= 0) + return OP_SUCCESS; + + bool timed_failed = false; + if (o.debugging > 3) + log_write(LOG_PLAIN, "[%s] Checking for timed probe timeouts...\n", this->target_host->targetipstr()); + for (unsigned int i = 0; i < this->timed_probes; i++) { + assert(this->fp_probes[i].isTimed()); + + /* Skip probes that have already been answered, but count how many of + * them are there. */ + if (this->fp_responses[i]) { + timed_probes_answered++; + continue; + } + + /* If there is some timed probe for which we have already scheduled its + * retransmission but it hasn't been sent yet, break the loop. We don't + * have to worry about retransmitting these probes yet.*/ + if (this->fp_probes[i].getTimeSent().tv_sec == 0) + return OP_SUCCESS; + + /* If we got a total timeout for any of the timed probes, we shouldn't + * attempt more retransmissions. We set a flag to indicate that but we + * still stay in the loop because we want to mark as "failed" any other + * probes we have not yet checked. */ + if (this->fp_probes[i].probeFailed()) { + timed_failed = true; + continue; + } + + /* Now check if the timed probe has timed out. If it suffered a total + * time out (max retransmissions done and still no answer) then mark + * it as such. Otherwise, count it so we can retransmit the whole + * group of timed probes later if appropriate. */ + if (TIMEVAL_SUBTRACT(now, this->fp_probes[i].getTimeSent()) >= this->rto) { + if (o.debugging > 3) { + log_write(LOG_PLAIN, "[%s] timed probe %d (%s) timedout\n", + this->target_host->targetipstr(), i, this->fp_probes[i].getProbeID()); + } + if (this->fp_probes[i].getRetransmissions() >= o.maxOSTries()) { + if (o.debugging > 3) + log_write(LOG_PLAIN, "[%s] Timed probe #%d (%s) failed after %d retransmissions.\n", this->target_host->targetipstr(), i, this->fp_probes[i].getProbeID(), this->fp_probes[i].getRetransmissions()); + this->fp_probes[i].setFailed(); + /* Let the network controller know that we don't expect a response + * for the probe anymore so the number of outstanding probes is + * reduced and the effective window is incremented. */ + this->netctl->cc_report_final_timeout(); + /* Also, increase our unanswered counter so we can later decide + * if the process has finished. */ + this->probes_unanswered++; + } else { + if (o.debugging > 3) + log_write(LOG_PLAIN, "[%s] Timed probe #%d (%s) has timed out (%d retransmissions done).\n", this->target_host->targetipstr(), i, this->fp_probes[i].getProbeID(), this->fp_probes[i].getRetransmissions()); + timed_probes_timedout++; + } + } + } + + if (o.debugging > 3) + log_write(LOG_PLAIN, "[%s] Timed_probes=%d, answered=%u, timedout=%u\n", this->target_host->targetipstr(), this->timed_probes, timed_probes_answered, timed_probes_timedout); + + /* If the probe that has timed out is a "timed probe" it means that + * we need to retransmit all timed probes, not only this one. For + * that, we wait until all timed probes have either timed out or + * been responded. When that happens, we do the following: + * 1) Store the responses we have received the last time we sent + * the timed probes in an aux array (this->aux_resp). + * 2) Clear the responses to the timed probes from the main + * response array (this->fp_responses). + * 3) Schedule the retransmission of all timed probes, 100ms apart. */ + if (this->timed_probes > 0 && timed_failed == false && timed_probes_timedout > 0 && (timed_probes_answered + timed_probes_timedout == this->timed_probes)) { + + /* Count the number of responses we have now and the number + * of responses we stored in the aux buffer last time. */ + unsigned int responses_stored = 0; + unsigned int responses_now = 0; + for (unsigned int j = 0; j < this->timed_probes; j++) { + if (this->aux_resp[j] != NULL) + responses_stored++; + if (this->fp_responses[j] != NULL) + responses_now++; + } + + /* If now we have more responses than before, copy our current + * set of responses to the aux array. Otherwise, just + * delete the current set of responses. */ + for (unsigned int k = 0; k < this->timed_probes; k++) { + if (responses_now > responses_stored) { + /* Free previous allocations */ + if (this->aux_resp[k] != NULL) { + delete this->aux_resp[k]; + } + /* Move the current response to the aux array */ + this->aux_resp[k] = this->fp_responses[k]; + this->fp_responses[k] = NULL; + } else { + delete this->fp_responses[k]; + this->fp_responses[k] = NULL; + } + } + + /* Update answer count because now we expect new answers to the timed probes. */ + assert(((int)this->probes_answered - (int)timed_probes_answered) >= 0); + this->probes_answered-= timed_probes_answered; + if (o.debugging > 3) + log_write(LOG_PLAIN, "[%s] Adjusting answer count: before=%d, after=%d\n", this->target_host->targetipstr(), this->probes_answered + timed_probes_answered, this->probes_answered); + + + /* Finally do the actual retransmission. Like the first time, + * we schedule them 100ms apart, starting at same random point + * between right now and 99ms. */ + int whentostart = get_random_u8()%100; + for (size_t l = 0; l < this->timed_probes; l++) { + this->fp_probes[l].incrementRetransmissions(); + this->fp_probes[l].resetTimeSent(); + this->netctl->scheduleProbe(&(this->fp_probes[l]), whentostart + l*100); + } + if (o.debugging > 3 && this->timed_probes > 0) + log_write(LOG_PLAIN, "[%s] Retransmitting timed probes (rcvd_before=%u, rcvd_now=%u times=%d).\n", this->target_host->targetipstr(), responses_stored, responses_now, this->fp_probes[0].getRetransmissions()); + + /* Reset our local counters. */ + timed_probes_answered = 0; + timed_probes_timedout = 0; + } + } + return OP_FAILURE; +} + + +/* This method is called when we detect that the OS detection process for this + * host is completed. It basically updates the host's internal state to + * indicate that the processed finished and unregisters the host from the + * network controller so we don't get any more callbacks. Here we also handle + * the special case of the retransmitted "timed probes". When we have to + * retransmit such probes, we usually have two sets of responses: the ones we + * got for the last retransmission, and the ones we got in the best try before + * that. So what we have to do is to decide which set is the best and discard + * the other one.*/ +int FPHost6::set_done_and_wrap_up() { + assert(this->probes_answered + this->probes_unanswered == this->total_probes); + + /* Inform the network controller that we do not wish to continue + * receiving callbacks (it could happen if the system had some other + * connections established with the target) */ + this->netctl->unregister_caller(this); + + /* Set up an internal flag to indicate we have finished */ + this->detection_done = true; + + /* Check the state of the timed probe retransmissions. In particular if we + * retransmitted timed probes, we should have two sets of responses, + * the ones we got last time we retransmitted, and the best set of responses + * we got out of all previous retransmissions but the last one. So now, we + * determine which set is the best and discard the other one. Btw, none of + * these loops run if timed_probes == 0, so it's safe in all cases. */ + + /* First count the number of responses in each set. */ + unsigned int stored = 0; + unsigned int current = 0; + for (unsigned int i = 0; i < this->timed_probes; i++) { + if (this->aux_resp[i] != NULL) + stored++; + if (this->fp_responses[i] != NULL) + current++; + } + /* If we got more responses in a previous try, use them and get rid of + * the current ones. */ + if (stored > current) { + for (unsigned int i = 0; i < this->timed_probes; i++) { + if (this->fp_responses[i] != NULL) + delete this->fp_responses[i]; + this->fp_responses[i] = this->aux_resp[i]; + this->aux_resp[i] = NULL; + } + /* Otherwise, get rid of the stored responses, use the current set */ + } else { + for (unsigned int i = 0; i < this->timed_probes; i++) { + if (this->aux_resp[i] != NULL) { + delete this->aux_resp[i]; + this->aux_resp[i] = NULL; + } + } + } + + return OP_SUCCESS; +} + + +/* This function is called by the network controller every time a packet of + * interest is captured. A "packet of interest" is a packet whose source + * address matches the IP address of the target associated with the FPHost + * instance. Inside the method, the received packet is processed in order to + * determine if it corresponds to a response to a previous FPProbe sent to + * that target. If the packet is a proper response, it will be stored for + * later processing, as it is part of the target's stack fingerprint. Returns + * a positive integer when the supplied packet could be successfully matched with + * a previously sent probe. The returned value indicates how many times the + * probe was sent before getting a reply: a return value of 1 means that we + * got a normal reply, value two means that we had to retransmit the packet + * once to get the reply, and so on. A return value of zero is a special case + * that indicates that the supplied packet is a response to a timed probed + * for which we already had received a reply in the past. This is necessary + * because we need to indicate the network controller that this is not a normal + * response to a retransmitted probe, and so, it should not be used to alter + * congestion control parameters. A negative return value indicates that the + * supplied packet is not a response to any probe sent by this host. */ +int FPHost6::callback(const u8 *pkt, size_t pkt_len, const struct timeval *tv) { + PacketElement *rcvd = NULL; + /* Dummy packet to ensure destruction of rcvd. */ + FPPacket dummy; + bool match_found = false; + int times_tx = 0; + + /* Make sure we still expect callbacks */ + if (this->detection_done) + return -1; + + if (o.debugging > 3) + log_write(LOG_PLAIN, "[%s] Captured %lu bytes\n", this->target_host->targetipstr(), (unsigned long)pkt_len); + + /* Convert the ugly raw buffer into a nice chain of PacketElement objects, so + * it's easier to parse the captured packet */ + if ((rcvd = PacketParser::split(pkt, pkt_len, false)) == NULL) + return -2; + dummy.setPacket(rcvd); + + /* Iterate over the list of sent probes and determine if the captured + * packet is a response to one of them. */ + for (unsigned int i = 0; i < this->probes_sent; i++) { + /* Skip probes for which we already got a response */ + if (this->fp_responses[i]) + continue; + + /* See if the received packet is a response to a probe */ + if (this->fp_probes[i].isResponse(rcvd)) { + struct timeval now, time_sent; + + gettimeofday(&now, NULL); + this->fp_responses[i] = new FPResponse(this->fp_probes[i].getProbeID(), + pkt, pkt_len, fp_probes[i].getTimeSent(), *tv); + this->fp_probes[i].incrementReplies(); + match_found = true; + + /* If the response that we've received is for a timed probe, we + * need to do a special handling. We don't want to report that + * we've received a response after N retransmissions because we + * may have re-sent the packet even if we got a response in the past. + * This happens when one of the timed probes times out and we + * retransmit all of them. We don't want the network controller to + * think there is congestion, so we only return the number of + * retransmissions if we didn't get a response before and we did now. */ + if (this->fp_probes[i].isTimed() && this->fp_probes[i].getRetransmissions() > 0 && this->fp_probes[i].getReplies() > 1) { + times_tx = 0; // Special case. + } else { + times_tx = this->fp_probes[i].getRetransmissions()+1; + } + this->probes_answered++; + /* Recompute the Retransmission Timeout based on this new RTT observation. */ + time_sent = this->fp_probes[i].getTimeSent(); + assert(time_sent.tv_sec > 0); + this->update_RTO(TIMEVAL_SUBTRACT(now, time_sent), this->fp_probes[i].getRetransmissions() != 0); + break; + } + } + + if (match_found) { + if (o.packetTrace()) { + log_write(LOG_PLAIN, "RCVD "); + rcvd->print(stdout, LOW_DETAIL); + log_write(LOG_PLAIN, "\n"); + } + /* Here, check if with this match we completed the OS detection */ + if (this->probes_answered + this->probes_unanswered == this->total_probes) { + /* Update our internal state to indicate we have finished */ + this->set_done_and_wrap_up(); + } + /* Return the number of times that the packet was transmitted before + * getting the reply. */ + return times_tx; + } else { + return -3; + } +} + + +const FPProbe *FPHost6::getProbe(const char *id) { + unsigned int i; + + for (i = 0; i < NUM_FP_PROBES_IPv6; i++) { + if (!this->fp_probes[i].is_set()) + continue; + if (strcmp(this->fp_probes[i].getProbeID(), id) == 0) + return &this->fp_probes[i]; + } + + return NULL; +} + +const FPResponse *FPHost6::getResponse(const char *id) { + unsigned int i; + + for (i = 0; i < NUM_FP_PROBES_IPv6; i++) { + if (this->fp_responses[i] == NULL) + continue; + if (strcmp(this->fp_responses[i]->probe_id, id) == 0) + return this->fp_responses[i]; + } + + return NULL; +} + + +/****************************************************************************** + * Implementation of class FPPacket. * + ******************************************************************************/ +FPPacket::FPPacket() { + this->pkt = NULL; + this->__reset(); +} + + +FPPacket::~FPPacket() { + this->__reset(); +} + + +/* Resets all internal state, freeing any previously stored packets */ +void FPPacket::__reset() { + this->link_eth = false; + memset(&(this->eth_hdr), 0, sizeof(struct eth_nfo)); + + PacketElement *me = this->pkt, *aux = NULL; + while (me != NULL) { + aux = me->getNextElement(); + delete me; + me = aux; + } + this->pkt = NULL; + memset(&this->pkt_time, 0, sizeof(struct timeval)); +} + + +/* Returns true if the FPPacket has been associated with a packet (through a + * call to setPacket(). This is equivalent to the following conditional: + * fppacket.getPacket() != NULL */ +bool FPPacket::is_set() const { + if (this->pkt != NULL) + return true; + else + return false; +} + + +/* Associates de FPPacket instance with the first protocol header of a networkj + * packet. Such header may be linked to others through the setNextElement() + * mechanism. Note that FPPacket does NOT make a copy of the contents of the + * supplied pointer, it just stores the memory address. Therefore, the caller + * MUST ensure that the supplied pointer remains valid during the lifetime of + * the FPPacket instance. + * + * After calling this function, the FPPacket takes ownership of pkt and will + * delete pkt in its destructor. */ +int FPPacket::setPacket(PacketElement *pkt) { + assert(pkt != NULL); + this->pkt = pkt; + return OP_SUCCESS; +} + + +/* Returns a newly allocated byte array with packet contents. The caller is + * responsible for freeing the buffer. */ +u8 *FPPacket::getPacketBuffer(size_t *pkt_len) const { + u8 *pkt_buff; + + pkt_buff = (u8 *)safe_malloc(this->pkt->getLen()); + this->pkt->dumpToBinaryBuffer(pkt_buff, this->pkt->getLen()); + + *pkt_len = (size_t)this->pkt->getLen(); + + return pkt_buff; +} + + +/* Returns a pointer to first header of the packet associated with the FPPacket + * instance. Note that this method will return NULL unless a previous call to + * setPacket() has been made. */ +const PacketElement *FPPacket::getPacket() const { + return this->pkt; +} + + +/* Returns the length of the packet associated with the FPPacket instance. Note + * that this method will return zero unless an actual packet was associated + * with the FPPacket object through a call to setPacket(). */ +size_t FPPacket::getLength() const { + if (this->pkt != NULL) + return this->pkt->getLen(); + else + return 0; +} + + +/* This method associates some link layer information with the packet. If + * sending at the ethernet level is not required, just call it passing NULL + * values, like this: instance.setEthernet(NULL, NULL, NULL); + * Otherwise, pass the source address, the next hop address and the name of + * the network interface the packet should be injected through. */ +int FPPacket::setEthernet(const u8 *src_mac, const u8 *dst_mac, const char *devname) { + if (src_mac == NULL || dst_mac == NULL) { + memset(&(this->eth_hdr), 0, sizeof(struct eth_nfo)); + this->link_eth = false; + return OP_FAILURE; + } + memcpy(this->eth_hdr.srcmac, src_mac, 6); + memcpy(this->eth_hdr.dstmac, dst_mac, 6); + this->link_eth = true; + if (devname != NULL) { + strncpy(this->eth_hdr.devname, devname, sizeof(this->eth_hdr.devname)-1); + if ((this->eth_hdr.ethsd = eth_open_cached(devname)) == NULL) + fatal("%s: Failed to open ethernet device (%s)", __func__, devname); + } else { + this->eth_hdr.devname[0] = '\0'; + this->eth_hdr.ethsd = NULL; + } + return OP_SUCCESS; +} + + +/* Returns an eth_nfo structure that contains the necessary parameters to + * allow the transmission of the packet at the Ethernet level. Note that + * such structure is only returned if a previous call to setEthernet() has + * been made. If it hasn't, this means that the packet should be sent at + * the IP layer, and only NULL will be returned. */ +const struct eth_nfo *FPPacket::getEthernet() const { + if (this->link_eth == true) + return &(this->eth_hdr); + else + return NULL; +} + + +/* Sets the internal time holder to the current time. */ +int FPPacket::setTime(const struct timeval *tv) { + if (tv != NULL) { + this->pkt_time = *tv; + return 0; + } else { + return gettimeofday(&this->pkt_time, NULL); + } +} + + +/* Returns the value of the internal time holder */ +struct timeval FPPacket::getTime() const { + return this->pkt_time; +} + + +/* Sets the internal time holder to zero. */ +int FPPacket::resetTime() { + memset(&this->pkt_time, 0, sizeof(struct timeval)); + return OP_SUCCESS; +} + + + +/****************************************************************************** + * Implementation of class FPProbe. * + ******************************************************************************/ +FPProbe::FPProbe() { + this->probe_id = NULL; + this->host = NULL; + this->reset(); +} + + +FPProbe::~FPProbe() { + if (this->probe_id != NULL) + free(this->probe_id); +} + + +void FPProbe::reset() { + this->probe_no = 0; + this->retransmissions = 0; + this->times_replied = 0; + this->failed = false; + this->timed = false; + if (this->probe_id != NULL) + free(this->probe_id); + this->probe_id = NULL; + + /* Also call FPPacket::__reset() to free any exising packet information */ + this->__reset(); +} + + +/* Returns true if the supplied packet is a response to this FPProbe. This + * method handles IPv4, IPv6, ICMPv4, ICMPv6, TCP and UDP. Basically it uses + * PacketParser::is_response(). Check there for a list of matched packets and + * some usage examples.*/ +bool FPProbe::isResponse(PacketElement *rcvd) { + return PacketParser::is_response(this->pkt, rcvd); +} + + +/* Store this probe's textual identifier. Note that this method makes a copy + * of the supplied string, so you can safely change its contents without + * affecting the object's state. */ +int FPProbe::setProbeID(const char *id) { + this->probe_id = strdup(id); + return OP_SUCCESS; +} + + +/* Returns a pointer to probe's textual identifier. */ +const char *FPProbe::getProbeID() const { + return this->probe_id; +} + + +/* Returns the number of times the probe has been scheduled for retransmission. */ +int FPProbe::getRetransmissions() const { + return this->retransmissions; +} + + +/* Increment the number of times the probe has been scheduled for retransmission + * by one unit. It returns the current value of the retransmission counter. */ +int FPProbe::incrementRetransmissions() { + this->retransmissions++; + return this->retransmissions; +} + + +/* Returns the number of times the probe has been replied. This applies for + * timed probes, which may be retransmitted even if we got a reply (becase + * another timed probe timeout and we had to retransmit all of them to keep + * the timing accurate). */ +int FPProbe::getReplies() const { + return this->times_replied; +} + + +/* Increment the number of times the probe has been replied. It returns the + * current value of the reply counter. */ +int FPProbe::incrementReplies() { + this->times_replied++; + return this->times_replied; +} + + +/* Sets the time at which the probe was sent */ +int FPProbe::setTimeSent() { + return this->setTime(); +} + + +/* Returns the time at which te packet was sent */ +struct timeval FPProbe::getTimeSent() const { + return this->getTime(); +} + + +/* Sets the time at which the probe was sent to zero. */ +int FPProbe::resetTimeSent() { + return this->resetTime(); +} + +/* Returns true if this FPProbe did not receive any response after all + * necessary retransmissions. When it returns true, callers should not + * attempt to change the state of the FPProbe. */ +bool FPProbe::probeFailed() const { + return this->failed; +} + + +/* This method should be called when the probe has been retransmitted as many + * times as we could and it still timed out without a response. Once this + * method is called, the state is irreversible (unless a call to FPProbe::reset() + * is made, in which case all internal state disappears) */ +int FPProbe::setFailed() { + this->failed = true; + return OP_SUCCESS; +} + + +/* Returns true if the probe is one of the "timed probes". */ +bool FPProbe::isTimed() const { + return this->timed; +} + + +/* Marks the probe as "timed". This is used to indicate that this probe has + * specific timing requirements (it must be sent exactly 100ms after the + * previous probe)., */ +int FPProbe::setTimed() { + this->timed = true; + return OP_SUCCESS; +} + + +/****************************************************************************** + * Implementation of class FPResponse. * + ******************************************************************************/ +FPResponse::FPResponse(const char *probe_id, const u8 *buf, size_t len, + struct timeval senttime, struct timeval rcvdtime) { + this->probe_id = string_pool_insert(probe_id); + this->buf = (u8 *) safe_malloc(len); + memcpy(this->buf, buf, len); + this->len = len; + this->senttime = senttime; + this->rcvdtime = rcvdtime; +} + + +FPResponse::~FPResponse() { + free(buf); +} + + +/****************************************************************************** + * Nsock handler wrappers. * + ******************************************************************************/ + +/* This handler is a wrapper for the FPNetworkControl::probe_transmission_handler() + * method. We need this because C++ does not allow to use class methods as + * callback functions for things like signal() or the Nsock lib. */ +void probe_transmission_handler_wrapper(nsock_pool nsp, nsock_event nse, void *arg) { + global_netctl.probe_transmission_handler(nsp, nse, arg); + return; +} + + +/* This handler is a wrapper for the FPNetworkControl:response_reception_handler() + * method. We need this because C++ does not allow to use class methods as + * callback functions for things like signal() or the Nsock lib. */ +void response_reception_handler_wrapper(nsock_pool nsp, nsock_event nse, void *arg) { + global_netctl.response_reception_handler(nsp, nse, arg); + return; +} diff --git a/FPEngine.h b/FPEngine.h new file mode 100644 index 0000000000..02761aa54d --- /dev/null +++ b/FPEngine.h @@ -0,0 +1,437 @@ + +/*************************************************************************** + * FPEngine.h -- Header info for IPv6 OS detection via TCP/IP * + * fingerprinting. For more information on how this works in Nmap, see * + * http://insecure.org/osdetect/ * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ + +/* $Id$ */ + +#ifndef __FPENGINE_H__ +#define __FPENGINE_H__ 1 + +#include "nsock.h" +#include +#include +#include "nmap.h" +#include "libnetutil/npacket.h" +using namespace std; + +/* Mention some classes here so we don't have to place the declarations in + * the right order (otherwise the compiler complains). */ +class FPHost; +class FPHost6; +class FPProbe; + +class Target; +class FingerPrintResultsIPv6; + +/****************************************************************************** + * CONSTANT DEFINITIONS * + ******************************************************************************/ + +#define NELEMS(a) (sizeof(a) / sizeof((a)[0])) + +#define NUM_FP_PROBES_IPv6_TCP 13 +#define NUM_FP_PROBES_IPv6_ICMPv6 4 +#define NUM_FP_PROBES_IPv6_UDP 1 +/* Total number of IPv6 OS detection probes. */ +#define NUM_FP_PROBES_IPv6 (NUM_FP_PROBES_IPv6_TCP+NUM_FP_PROBES_IPv6_ICMPv6+NUM_FP_PROBES_IPv6_UDP) + +const unsigned int OSDETECT_FLOW_LABEL = 0x12345; + + + +/* Number of timed probes for IPv6 OS scan. This is, the number of probes that + * have specific timing requirements and need to be processed together. This + * are the probes that are sent 100ms apart. */ +#define NUM_FP_TIMEDPROBES_IPv6 6 + +/* Initial congestion window. It is set to the number of timed probes because + * hosts need to be able to schedule all of them at once. */ +#define OSSCAN_INITIAL_CWND (NUM_FP_TIMEDPROBES_IPv6) + +/* Initial Slow Start threshold. It is set to four times the initial CWND. */ +#define OSSCAN_INITIAL_SSTHRESH (4 * OSSCAN_INITIAL_CWND) + +/* Host group size is the number of osscan hosts that are processed in parallel. + * Note that this osscan engine always keeps a working group of this many hosts. + * in other words, if one host in the group finishes, another is added to it + * dynamically. */ +#define OSSCAN_GROUP_SIZE 10 + +/* Initial retransmission timeout. This is the time we initially wait for a + * probe response before retransmitting the original probe. Note that this is + * only the initial RTO, used only when no RTT measures have been taken yet. + * The actual RTO varies each time we get a response to a probe. + * It is set to 3 seconds (3*10^6 usecs) as per RFC 2988. */ +#define OSSCAN_INITIAL_RTO (3*1000000) + + +/****************************************************************************** + * CLASS DEFINITIONS * + ******************************************************************************/ + +/* This class handles the access to the network. It handles packet transmission + * scheduling, packet capture and congestion control. Every FPHost should be + * linked to the same instance of this class, so the access to the network can + * be managed globally (for the whole OS detection process). */ +class FPNetworkControl { + + private: + nsock_pool nsp; /* Nsock pool. */ + nsock_iod pcap_nsi; /* Nsock Pcap descriptor. */ + nsock_event_id pcap_ev_id; /* Last pcap read event that was scheduled. */ + bool first_pcap_scheduled; /* True if we scheduled the first pcap read event. */ + bool nsock_init; /* True if the nsock pool has been initialized. */ + int rawsd; /* Raw socket. */ + vector callers; /* List of users of this instance (used for callbacks).*/ + int probes_sent; /* Number of unique probes sent (not retransmissions). */ + int responses_recv; /* Number of probe responses received. */ + int probes_timedout; /* Number of probes that timeout after all retransms. */ + float cc_cwnd; /* Current congestion window. */ + float cc_ssthresh; /* Current Slow Start threshold. */ + + int cc_init(); + int cc_update_sent(int pkts); + int cc_report_drop(); + int cc_update_received(); + + public: + FPNetworkControl(); + ~FPNetworkControl(); + void init(const char *ifname, devtype iftype); + int register_caller(FPHost *newcaller); + int unregister_caller(FPHost *oldcaller); + int setup_sniffer(const char *iface, const char *bfp_filter); + void handle_events(); + int scheduleProbe(FPProbe *pkt, int in_msecs_time); + void probe_transmission_handler(nsock_pool nsp, nsock_event nse, void *arg); + void response_reception_handler(nsock_pool nsp, nsock_event nse, void *arg); + bool request_slots(size_t num_packets); + int cc_report_final_timeout(); + +}; + +/* +-----------+ + | FPEngine | + +-----------+ + | | + +-----+-----+ + | + +-------+-------+ + | | + | | + +-----------+ +-----------+ + | FPEngine4 | | FPEngine6 | + +-----------+ +-----------+ + | | | | + +-----------+ +-----------+ */ +/* This class is the generic fingerprinting engine. */ +class FPEngine { + + protected: + size_t osgroup_size; + + public: + FPEngine(); + ~FPEngine(); + void reset(); + virtual int os_scan(vector &Targets) = 0; + const char *bpf_filter(vector &Targets); + +}; + + +/* This class handles IPv6 OS fingerprinting. Using it is very simple, just + * instance it and then call os_scan() with the list of IPv6 targets to + * fingerprint. If everything goes well, the internal state of the supplied + * target objects will be modified to reflect the results of the fingerprinting + * process. */ +class FPEngine6 : public FPEngine { + + private: + vector fphosts; /* Information about each target to fingerprint */ + + public: + FPEngine6(); + ~FPEngine6(); + void reset(); + int os_scan(vector &Targets); + +}; + + +/* +----------+ + | FPPacket | + +----------+ + | | + +-----+----+ + | + | + +-----------+ + | FPProbe | + +-----------+ + | | + +-----+-----+ */ +/* This class represents a generic packet for the OS fingerprinting process */ +class FPPacket { + + protected: + PacketElement *pkt; /* Actual packet associated with this FPPacket */ + bool link_eth; /* Ethernet layer required? */ + struct eth_nfo eth_hdr; /* Eth info, valid when this->link_eth==true */ + struct timeval pkt_time; /* Time at which the packet was sent or received */ + + int resetTime(); + void __reset(); + + public: + FPPacket(); + ~FPPacket(); + int setTime(const struct timeval *tv = NULL); + struct timeval getTime() const; + int setPacket(PacketElement *pkt); + int setEthernet(const u8 *src_mac, const u8 *dst_mac, const char *devname); + const struct eth_nfo *getEthernet() const; + const PacketElement *getPacket() const; + size_t getLength() const; + u8 *getPacketBuffer(size_t *pkt_len) const; + bool is_set() const; + +}; + +/* This class represents a generic OS fingerprinting probe. In other words, it + * represents a network packet that Nmap sends to a target in order to + * obtain information about the target's TCP/IP stack. */ +class FPProbe : public FPPacket { + + private: + char *probe_id; + int probe_no; + int retransmissions; + int times_replied; + bool failed; + bool timed; + + public: + FPHost *host; + + FPProbe(); + ~FPProbe(); + void reset(); + bool isResponse(PacketElement *rcvd); + int setProbeID(const char *id); + const char *getProbeID() const; + int getRetransmissions() const; + int incrementRetransmissions(); + int getReplies() const; + int incrementReplies(); + int setTimeSent(); + int resetTimeSent(); + struct timeval getTimeSent() const; + bool probeFailed() const; + int setFailed(); + bool isTimed() const; + int setTimed(); + +}; + +/* This class represents a generic received packet. */ +struct FPResponse { + const char *probe_id; + u8 *buf; + size_t len; + struct timeval senttime, rcvdtime; + + FPResponse(const char *probe_id, const u8 *buf, size_t len, + struct timeval senttime, struct timeval rcvdtime); + ~FPResponse(); +}; + + +/* +-----------+ + | FPHost | + +-----------+ + | | + +-----+-----+ + | + +-------+-------+ + | | + | | + +-----------+ +-----------+ + | FPHost4 | | FPHost6 | + +-----------+ +-----------+ + | | | | + +-----------+ +-----------+ */ +/* This class represents a generic host to be fingerprinted. */ +class FPHost { + + protected: + unsigned int total_probes; /* Number of different OS scan probes to be sent to targets */ + unsigned int timed_probes; /* Number of probes that have specific timing requirements */ + unsigned int probes_sent; /* Number of FPProbes sent (not counting retransmissions) */ + unsigned int probes_answered; /* Number of FPResponses received */ + unsigned int probes_unanswered; /* Number of FPProbes that timedout (after all retransmissions) */ + bool detection_done; /* True if the OS detection process has been completed. */ + bool timedprobes_sent; /* True if the probes that have timing requirements were sent */ + Target *target_host; /* Info about the host to fingerprint */ + FPNetworkControl *netctl; /* Link to the network manager (for scheduling and CC) */ + bool netctl_registered; /* True if we are already registered in the network controller */ + u32 tcpSeqBase; /* Base for sequence numbers set in outgoing probes */ + int open_port_tcp; /* Open TCP port to be used in the OS detection probes */ + int closed_port_tcp; /* Closed TCP port for the OS detection probes. */ + int closed_port_udp; /* Closed UDP port. */ + int tcp_port_base; /* Send TCP probes starting with this port number. */ + int udp_port_base; /* Send UDP probes with this port number. */ + u16 icmp_seq_counter; /* ICMPv6 sequence number counter. */ + int rto; /* Retransmission timeout for the host */ + int rttvar; /* Round-Trip Time variation (RFC 2988) */ + int srtt; /* Smoothed Round-Trip Time (RFC 2988) */ + + void __reset(); + int update_RTO(int measured_rtt_usecs, bool retransmission); + int choose_osscan_ports(); + + private: + virtual int build_probe_list() = 0; + + public: + struct timeval begin_time; + + FPHost(); + ~FPHost(); + virtual bool done() = 0; + virtual int schedule() = 0; + virtual int callback(const u8 *pkt, size_t pkt_len, const struct timeval *tv) = 0; + const struct sockaddr_storage *getTargetAddress(); + +}; + +/* This class represents IPv6 hosts to be fingerprinted. The class performs + * OS detection asynchronously. To use it, shedule() must be called at regular + * intervals until done() returns true. After that, status() will indicate + * whether the host was successfully matched with a particular OS or not. */ +class FPHost6 : public FPHost { + + private: + FPProbe fp_probes[NUM_FP_PROBES_IPv6]; /* OS detection probes to be sent.*/ + FPResponse *fp_responses[NUM_FP_PROBES_IPv6]; /* Received responses. */ + FPResponse *aux_resp[NUM_FP_TIMEDPROBES_IPv6]; /* Aux vector for timed responses */ + + int build_probe_list(); + int set_done_and_wrap_up(); + + public: + FPHost6(Target *tgt, FPNetworkControl *fpnc); + ~FPHost6(); + void reset(); + void init(Target *tgt, FPNetworkControl *fpnc); + void finish(); + bool done(); + int schedule(); + int callback(const u8 *pkt, size_t pkt_len, const struct timeval *tv); + const FPProbe *getProbe(const char *id); + const FPResponse *getResponse(const char *id); + + void fill_FPR(FingerPrintResultsIPv6 *FPR); + +}; + + +/****************************************************************************** + * Nsock handler wrappers. * + ******************************************************************************/ + +void probe_transmission_handler_wrapper(nsock_pool nsp, nsock_event nse, void *arg); +void response_reception_handler_wrapper(nsock_pool nsp, nsock_event nse, void *arg); + + +std::vector load_fp_matches(); + + +#endif /* __FPENGINE_H__ */ diff --git a/FPmodel.cc b/FPmodel.cc new file mode 100644 index 0000000000..58f6ca5766 --- /dev/null +++ b/FPmodel.cc @@ -0,0 +1,1590 @@ +/* This file is automatically generated. */ + +#include "FingerPrintResults.h" +#include "linear.h" + +double FPscale[][2] = { + { -20, 0.0416667 }, + { -0, 0.00520833 }, + { -20, 0.0416667 }, + { -0, 0.00520833 }, + { -20, 0.05 }, + { -0, 0.00520833 }, + { -20, 0.0416667 }, + { -0, 0.00520833 }, + { -20, 0.0416667 }, + { -0, 0.00520833 }, + { -20, 0.05 }, + { -0, 0.00520833 }, + { -128, 0.0333333 }, + { -0, 1 }, + { -80, 0.0625 }, + { -0, 1 }, + { -16, 0.015625 }, + { -0, 1 }, + { -24, 0.125 }, + { -0, 0.00446429 }, + { -356, 1 }, + { -0, 1 }, + { -20, 0.0833333 }, + { -0, 0.00520833 }, + { -20, 1 }, + { -0, 0.00520833 }, + { -20, 0.0416667 }, + { -0, 0.2 }, + { -20, 1 }, + { -0, 0.00520833 }, + { -20, 1 }, + { -0, 0.00520833 }, + { -20, 1 }, + { -0, 0.00520833 }, + { -20, 1 }, + { -0, 0.00520833 }, + { -0, 2.32835e-11 }, + { -0, 1.5259e-05 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -1, 0.333333 }, + { -1, 0.142857 }, + { -1, 0.142857 }, + { -1, 0.333333 }, + { -1, 0.142857 }, + { -1, 0.142857 }, + { -1, 0.142857 }, + { -0, 1 }, + { -0, 0.125 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -1, 0.333333 }, + { -1, 0.111111 }, + { -1, 0.111111 }, + { -1, 0.333333 }, + { -1, 0.111111 }, + { -1, 0.111111 }, + { -1, 0.111111 }, + { -1, 1 }, + { -1, 0.111111 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -1220, 6.59805e-05 }, + { -1, 1 }, + { -0, 0.125 }, + { -0, 1.5259e-05 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -1, 0.333333 }, + { -1, 0.142857 }, + { -1, 0.142857 }, + { -1, 0.333333 }, + { -1, 0.142857 }, + { -1, 0.142857 }, + { -1, 0.142857 }, + { -0, 1 }, + { -0, 0.125 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -1, 0.333333 }, + { -1, 0.111111 }, + { -1, 0.111111 }, + { -1, 0.333333 }, + { -1, 0.111111 }, + { -1, 0.111111 }, + { -1, 0.111111 }, + { -1, 1 }, + { -1, 0.111111 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -1220, 6.59805e-05 }, + { -1, 1 }, + { -0, 0.125 }, + { -0, 1.5259e-05 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -1, 1 }, + { -1, 1 }, + { -1, 0.142857 }, + { -1, 0.142857 }, + { -1, 1 }, + { -3, 0.2 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -1, 0.333333 }, + { -1, 1 }, + { -1, 0.111111 }, + { -1, 0.111111 }, + { -1, 1 }, + { -3, 0.142857 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -640, 6.35486e-05 }, + { -0, 1 }, + { -0, 0.125 }, + { -0, 1.5259e-05 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -1, 0.333333 }, + { -1, 0.142857 }, + { -1, 0.142857 }, + { -1, 0.333333 }, + { -1, 0.142857 }, + { -1, 0.142857 }, + { -1, 0.142857 }, + { -0, 1 }, + { -0, 0.125 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -1, 0.333333 }, + { -1, 0.111111 }, + { -1, 0.111111 }, + { -1, 0.333333 }, + { -1, 0.111111 }, + { -1, 0.111111 }, + { -1, 0.111111 }, + { -1, 1 }, + { -1, 0.111111 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -516, 6.30517e-05 }, + { -1, 1 }, + { -0, 0.125 }, + { -0, 1.5259e-05 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -1, 0.333333 }, + { -1, 0.142857 }, + { -1, 0.142857 }, + { -1, 0.333333 }, + { -1, 0.142857 }, + { -1, 0.142857 }, + { -1, 0.142857 }, + { -0, 1 }, + { -0, 0.125 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -1, 0.333333 }, + { -1, 0.111111 }, + { -1, 0.111111 }, + { -1, 0.333333 }, + { -1, 0.111111 }, + { -1, 0.111111 }, + { -1, 0.111111 }, + { -1, 1 }, + { -1, 0.111111 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -536, 6.31313e-05 }, + { -1, 1 }, + { -0, 0.125 }, + { -0, 1.5259e-05 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -1, 0.333333 }, + { -1, 0.142857 }, + { -1, 0.142857 }, + { -2, 0.166667 }, + { -1, 0.333333 }, + { -0, 1 }, + { -0, 0.125 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -1, 0.333333 }, + { -1, 0.111111 }, + { -1, 0.111111 }, + { -2, 0.125 }, + { -1, 1 }, + { -1, 1 }, + { -1, 0.111111 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -265, 6.20694e-05 }, + { -1, 1 }, + { -0, 1 }, + { -0, 1.5259e-05 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -2, 1 }, + { -1, 1 }, + { -1, 0.5 }, + { -1, 0.333333 }, + { -0, 1 }, + { -0, 0.25 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -4, 1 }, + { -1, 1 }, + { -1, 0.5 }, + { -1, 1 }, + { -1, 1 }, + { -1, 0.5 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -1220, 6.59805e-05 }, + { -1, 1 }, + { -0, 0.125 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -1, 1 }, + { -0, 1 }, + { -1, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1.5259e-05 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -1, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -2, 0.5 }, + { -1, 0.142857 }, + { -1, 0.142857 }, + { -1, 0.333333 }, + { -1, 0.142857 }, + { -3, 0.2 }, + { -4, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -2, 0.5 }, + { -1, 0.111111 }, + { -1, 0.111111 }, + { -1, 1 }, + { -1, 0.111111 }, + { -3, 0.142857 }, + { -2, 1 }, + { -1, 1 }, + { -1, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -265, 6.20694e-05 }, + { -1, 1 }, + { -1, 0.166667 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -1, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -1, 1 }, + { -0, 1 }, + { -1, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -1, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -1, 1 }, + { -0, 1 }, + { -1, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, + { -0, 1 }, +}; + +static double _w[] = { + -0.03401705, -0.06478774, -0.01648169, -0.02551762, -0.05025502, +0.04682426, +0.03085423, +0.03248408, -0.06730305, +0.04214657, +0.03105325, +0.04235073, -0.01664211, -0.02696274, +0.03321320, -0.02919341, -0.01434072, -0.00836606, +0.02229972, +0.02448222, -0.05222024, -0.02154076, -0.02033894, + -0.00108857, -0.01210963, -0.08984361, -0.00134331, -0.00888238, -0.00067107, -0.00044780, -0.00549996, -0.01332157, -0.00708374, -0.00231837, -0.00025663, -0.00240440, -0.00795039, -0.00154933, -0.00201376, -0.05201523, -0.00551265, -0.00420591, -0.00276018, -0.00081651, -0.00282863, +0.16306692, + -0.03401705, -0.06478774, -0.01648169, -0.02551762, -0.05025502, +0.04682426, +0.03085423, +0.03248408, -0.06730305, +0.04214657, +0.03105325, +0.04235073, -0.01664211, -0.02696274, +0.03321320, -0.02919341, -0.01434072, -0.00836606, +0.02229972, +0.02448222, -0.05222024, -0.02154076, -0.02033894, + -0.00108857, -0.01210963, -0.08984361, -0.00134331, -0.00888238, -0.00067107, -0.00044780, -0.00549996, -0.01332157, -0.00708374, -0.00231837, -0.00025663, -0.00240440, -0.00795039, -0.00154933, -0.00201376, -0.05201523, -0.00551265, -0.00420591, -0.00276018, -0.00081651, -0.00282863, +0.16306692, + +0.00527294, -0.09775388, -0.06100692, +0.01661974, -0.19506927, +0.00717403, -0.00179878, +0.01433855, -0.10209799, +0.02425316, +0.00714278, -0.00101959, +0.00821922, +0.01696060, -0.00823500, +0.01690085, -0.02237620, -0.03171187, +0.00129012, +0.00159451, +0.11055125, +0.03993739, -0.04451631, + -0.00108857, -0.01210963, -0.08984361, -0.00134331, -0.00888238, -0.00067107, -0.00044780, -0.00549996, -0.01332157, -0.00708374, -0.00231837, -0.00025663, -0.00240440, -0.00795039, -0.00154933, -0.00201376, -0.05201523, -0.00551265, -0.00420591, -0.00276018, -0.00081651, -0.00282863, +0.16306692, + -0.02952442, -0.06090029, -0.01127947, -0.01783883, -0.04360294, +0.05350986, +0.03306054, +0.03369992, -0.15556320, +0.04314106, +0.03230003, +0.04421267, +0.00102706, -0.02504472, +0.09317663, -0.00436532, -0.00725643, -0.00337134, +0.02446240, +0.02561645, -0.10680850, +0.00065641, -0.01722608, + +0.00351731, -0.00905534, -0.08468470, +0.00556431, -0.00340756, +0.00203357, +0.00074425, -0.00473076, -0.09612395, -0.00648743, -0.00115564, +0.00137211, +0.01539184, -0.00599722, +0.03953203, +0.02460384, -0.04507093, -0.00057618, -0.00239333, -0.00180130, -0.03734475, +0.01998053, +0.16613372, + -0.03268749, -0.06040510, -0.01343236, -0.01758163, -0.04703988, +0.05700738, +0.03641413, +0.03483935, -0.04722602, +0.04419090, +0.03155772, +0.04324807, -0.01450922, -0.02561980, +0.03711215, -0.02427532, -0.00638755, -0.00475450, +0.02543967, +0.02635522, -0.05585504, -0.01962068, -0.01621612, + -0.00041101, -0.00920980, -0.08712468, +0.00384656, -0.00712178, +0.00289460, +0.00230751, -0.00482210, -0.01379566, -0.00656216, -0.00205148, -0.00001077, -0.00080498, -0.00700106, +0.04857337, +0.00144446, -0.04483533, -0.00214791, -0.00295604, -0.00162756, -0.02786822, -0.00121405, +0.16625772, + -0.03395010, +0.05546751, -0.01431049, -0.01850537, -0.05527688, +0.05288511, +0.03493418, +0.01801397, -0.04958345, +0.01876096, +0.03030226, +0.04202893, -0.01622106, -0.02740768, +0.03551265, -0.02603132, -0.00960317, -0.00497368, +0.02268301, +0.01877254, -0.05846273, -0.02366479, -0.02348674, + -0.00041101, -0.00920980, -0.08712468, +0.00384656, -0.00712178, +0.00289460, +0.00230751, -0.00482210, -0.01379566, -0.00656216, -0.00205148, -0.00001077, -0.00080498, -0.00700106, +0.04857337, +0.00144446, -0.04483533, -0.00214791, -0.00295604, -0.00162756, -0.02786822, -0.00121405, +0.16625772, + +0.03752341, +0.02485110, +0.01966751, +0.06030777, +0.03914247, +0.04633695, +0.07743474, +0.04915095, -0.09619212, +0.07284456, +0.01056522, +0.01701360, -0.12019761, +0.01896763, -0.31245798, +0.47444473, +0.07306535, +0.03901353, +0.02398730, +0.00877182, -0.55251527, +0.41376725, +0.01448450, + +0.02140174, +0.01897168, +0.01647401, +0.03235163, +0.02149059, +0.02916177, +0.04790973, +0.03276665, -0.03730312, +0.04491106, +0.00714942, +0.01323502, -0.02115044, +0.01287521, -0.14740250, +0.16286727, +0.04470427, +0.02532533, +0.01858386, +0.01117321, -0.05860220, +0.09423041, +0.01650533, + +0.06421155, +0.03808108, +0.02558867, +0.07684293, +0.05380653, +0.09211965, +0.12676789, +0.11243309, -0.23302657, +0.16514169, +0.02393464, +0.03056902, -0.02951993, +0.07885978, -0.27317633, -0.34237408, +0.07670584, +0.04143494, -0.35387812, +0.08595730, -0.12946446, +0.61734092, +0.02334565, + +0.03474581, +0.02558667, +0.01943458, +0.04061921, +0.02882262, +0.05205312, +0.07257630, +0.06440772, -0.10572034, +0.09105963, +0.01383413, +0.02001273, +0.02418840, +0.04282128, -0.12776167, -0.24554214, +0.04652451, +0.02653603, -0.17034885, +0.04976595, +0.15292320, +0.19601725, +0.02093590, + +0.10101389, -0.04678150, -0.05392351, -0.02385274, -0.06357521, -0.06487671, +0.09617135, +0.11319233, -0.05145324, +0.15100934, -0.10479918, +0.15150772, -0.02297762, +0.25618388, -0.07309790, -0.06290518, +0.11032950, +0.07821491, -0.12553686, +0.10817013, -0.03952725, -0.07371091, -0.05597605, + +0.14273025, -0.04317707, -0.05018202, -0.01687891, -0.05345628, -0.06212077, +0.09711170, +0.11853803, -0.04438704, +0.15765690, -0.09967395, +0.15234200, -0.01496352, +0.10993760, -0.07198943, -0.04778168, +0.11238824, +0.08470690, -0.12253159, +0.11421832, -0.01796739, -0.05062893, -0.05059036, + -0.13776387, +0.15417716, -0.10813626, -0.06236244, +0.11842623, -0.11379043, -0.14710761, +0.06223974, +0.09975723, +0.07860233, -0.04811827, -0.07463097, +0.08594937, +0.19701155, +0.03408448, -0.31467762, +0.19151950, -0.14235680, -0.16079745, +0.34684874, -0.42998383, +0.40411579, +0.09296425, + -0.08486027, +0.04117626, -0.19136589, -0.04417114, +0.14052436, -0.06847299, -0.08055390, +0.09509263, +0.02711531, +0.12385740, -0.03750652, -0.06941794, +0.17412492, +0.07726670, +0.04730178, -0.24118195, +0.14708335, -0.14028616, -0.11833458, +0.15350474, -0.30523800, +0.18207718, +0.27292781, + +0.02761648, -0.09402474, +0.01780062, +0.03965922, +0.03169245, +0.04521880, -0.09816744, +0.02857531, -0.05611803, +0.03563119, +0.01005523, +0.00950815, -0.01548486, +0.04119474, +0.00602490, +0.17153391, +0.04841082, +0.02564342, +0.03172118, +0.07468060, -0.21972466, +0.11280625, +0.02538278, + +0.02761648, -0.09402474, +0.01780062, +0.03965922, +0.03169245, +0.04521880, -0.09816744, +0.02857531, -0.05611803, +0.03563119, +0.01005523, +0.00950815, -0.01548486, +0.04119474, +0.00602490, +0.17153391, +0.04841082, +0.02564342, +0.03172118, +0.07468060, -0.21972466, +0.11280625, +0.02538278, + -0.01120068, -0.10340759, -0.06626813, +0.00329186, +0.02099139, -0.00020140, -0.00502117, +0.01081054, -0.12386600, +0.02081478, +0.00362081, -0.00948701, -0.00390180, +0.01243708, +0.03725825, +0.00788369, -0.02365385, -0.03338566, -0.00126624, -0.00055412, +0.08076778, +0.00386253, -0.04716553, + -0.00108857, -0.01210963, -0.08984361, -0.00134331, -0.00888238, -0.00067107, -0.00044780, -0.00549996, -0.01332157, -0.00708374, -0.00231837, -0.00025663, -0.00240440, -0.00795039, -0.00154933, -0.00201376, -0.05201523, -0.00551265, -0.00420591, -0.00276018, -0.00081651, -0.00282863, +0.16306692, + -0.03051243, -0.01223842, +0.06192271, -0.00295116, -0.03499272, -0.00009132, +0.00927222, -0.01058823, -0.02518193, -0.01502829, +0.13467536, -0.08918981, -0.00326077, +0.12965824, +0.00929954, -0.01741536, +0.06530373, +0.04470146, -0.00732600, -0.00464145, -0.00334399, -0.02500172, +0.05667624, + -0.03160099, -0.02434805, -0.02792091, -0.00429447, -0.04387510, -0.00076240, +0.00882442, -0.01608818, -0.03850350, -0.02211203, +0.13235699, -0.08944644, -0.00566517, +0.12170785, +0.00775021, -0.01942913, +0.01328850, +0.03918881, -0.01153191, -0.00740164, -0.00416050, -0.02783035, +0.21974316, + +0.00160832, -0.03566876, +0.09683756, +0.03859490, +0.00726697, -0.04515920, -0.00931334, -0.08829082, -0.03012387, -0.11981557, +0.11212159, +0.18760958, +0.01505055, +0.05389225, -0.02167527, +0.03020195, -0.13999936, +0.15291442, -0.04637904, -0.03183887, -0.01374662, +0.03326258, -0.08652946, + +0.00432573, -0.03218607, +0.10561541, +0.04186582, +0.02252662, -0.03552573, -0.00181838, -0.07554663, -0.02966875, -0.10567261, -0.02968529, +0.28737198, +0.01906740, +0.06092522, -0.01792121, +0.03716615, -0.13927646, +0.15674797, -0.03525322, -0.02361677, -0.01205676, +0.03832206, -0.08473168, + +0.00817280, +0.00960566, +0.00491395, +0.01050476, +0.00515014, +0.01509031, -0.11244887, +0.00589050, -0.23529565, +0.00518800, +0.00477699, +0.00191498, +0.00491674, +0.02991267, +0.12747729, +0.00937796, +0.03275239, +0.01733398, +0.01946288, +0.06191324, +0.09919685, +0.00213021, +0.00793116, + +0.00708423, -0.00250397, -0.08492966, +0.00916145, -0.00373224, +0.01441923, -0.11289667, +0.00039055, -0.24861722, -0.00189575, +0.00245862, +0.00165835, +0.00251235, +0.02196228, +0.12592796, +0.00736420, -0.01926284, +0.01182133, +0.01525698, +0.05915305, +0.09838034, -0.00069842, +0.17099808, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01089003, +0.00900509, -0.08025537, +0.02632350, +0.00204174, +0.04238295, -0.08040539, +0.03107703, -0.07732683, +0.04139595, +0.00625133, +0.00976600, +0.00912702, +0.02605045, -0.10677594, +0.02468117, -0.00720929, +0.01685942, +0.02857900, +0.06815944, -0.03304860, +0.01765123, +0.17986055, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01089003, +0.00900509, -0.08025537, +0.02632350, +0.00204174, +0.04238295, -0.08040539, +0.03107703, -0.07732683, +0.04139595, +0.00625133, +0.00976600, +0.00912702, +0.02605045, -0.10677594, +0.02468117, -0.00720929, +0.01685942, +0.02857900, +0.06815944, -0.03304860, +0.01765123, +0.17986055, + +0.02423895, +0.03516026, +0.01188503, -0.10799360, +0.02939837, -0.07453347, -0.02116598, +0.05994469, -0.05957423, +0.07791474, +0.01992533, +0.01457123, +0.02452164, +0.04195439, -0.08102380, +0.04273385, +0.04859973, +0.02457240, +0.09078679, -0.10080879, +0.00187557, +0.05170431, +0.02061345, + +0.02315039, +0.02305063, -0.07795858, -0.10933691, +0.02051598, -0.07520454, -0.02161378, +0.05444473, -0.07289580, +0.07083100, +0.01760696, +0.01431460, +0.02211724, +0.03400400, -0.08257313, +0.04072009, -0.00341550, +0.01905975, +0.08658088, -0.10356897, +0.00105907, +0.04887568, +0.18368037, + -0.00427210, -0.00351428, +0.06969014, -0.03775647, -0.05268288, -0.08293037, -0.00845432, +0.01677261, +0.05941152, -0.02860224, -0.06356739, +0.05354832, +0.02932524, +0.03954812, -0.00890693, +0.41342033, -0.05788105, -0.04459421, +0.10342852, +0.03458854, -0.30334936, -0.25519368, +0.00378197, + +0.16451352, -0.05289310, -0.01376501, -0.02882971, -0.05403575, -0.06761200, -0.05521109, +0.06825307, +0.06212907, +0.08546922, -0.09733928, +0.13090238, -0.02434002, -0.03863623, +0.11231508, -0.06475020, -0.02054697, -0.01012042, +0.10218928, -0.08431031, -0.17624752, -0.03737194, -0.02225051, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + -0.01452142, -0.00430970, +0.04423652, +0.00030702, -0.00465681, -0.00354453, -0.00955817, -0.01146240, +0.00277608, -0.01155343, -0.00294877, -0.01138099, -0.01144859, -0.00090835, -0.10553252, -0.00265750, -0.08254550, -0.07488028, -0.00866185, -0.01125700, +0.08614999, -0.00426749, +0.03985199, + -0.00250888, -0.00778021, -0.05945176, -0.00704065, -0.00884110, -0.00305924, -0.00588574, -0.00410500, -0.00076526, -0.00471276, -0.00272716, -0.00095050, -0.00146849, -0.01024079, -0.02497383, -0.00639215, +0.07591474, +0.06611660, -0.00333065, -0.00224118, -0.00249786, -0.01104749, -0.05517682, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + -0.01810234, -0.01433848, -0.01556876, -0.01265466, -0.01391571, -0.01454221, -0.01361285, -0.01720067, -0.04572617, -0.01769885, -0.00588713, -0.01293452, -0.01413625, -0.01185478, +0.00347981, -0.01715230, +0.01470732, +0.00372905, -0.01439450, -0.01440496, -0.02081138, -0.01808364, -0.01685830, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + -0.00845317, +0.00668586, +0.05765258, +0.15335129, -0.00725228, -0.00388606, +0.00536336, +0.00365117, -0.00169181, +0.00434539, +0.00168581, -0.00102443, -0.00888937, +0.00737656, +0.02320724, -0.00666063, -0.07625187, -0.06794867, +0.00275199, -0.00008282, -0.01748099, -0.01393975, +0.05450763, + -0.00596814, +0.02131719, -0.05447449, +0.15632578, +0.01014653, -0.00297623, +0.00606711, +0.00989130, +0.01707366, +0.01205797, +0.00708100, -0.00010464, -0.00427861, +0.01911320, +0.02535905, +0.00055010, -0.02017254, -0.02656369, +0.00834420, +0.00329525, -0.01608867, -0.00965563, -0.04087919, + -0.09411772, -0.01457893, -0.09351218, -0.08935645, -0.07348070, +0.12405542, -0.01787757, -0.01032875, -0.02804962, -0.00845077, -0.01396356, -0.02634182, +0.05797780, -0.02840393, +0.00586776, +0.11010957, -0.03670833, -0.04305913, -0.02731527, -0.04048554, +0.14349876, +0.14199400, -0.06366944, + +0.13543975, +0.12200954, -0.06121995, -0.01937411, +0.20217113, -0.04385120, +0.08156606, -0.03274667, +0.00159948, -0.04472071, -0.01187587, -0.02447675, -0.02706412, +0.10727713, -0.05091630, -0.03483146, -0.01825676, -0.03006336, -0.05284204, +0.13656417, +0.03637327, -0.07068599, -0.05323033, + +0.15399813, +0.02192111, -0.05479140, -0.00268885, -0.00468070, +0.00789275, -0.00893644, +0.00477024, +0.03918486, +0.00535099, +0.00230339, -0.01242338, -0.01203643, +0.11752694, -0.02756864, -0.02404454, -0.01258268, -0.02822548, +0.00635952, -0.00130467, +0.05297544, -0.02873175, -0.04117884, + -0.06284727, +0.01830797, -0.01875022, -0.03450992, +0.12785541, +0.01037399, +0.00471379, +0.12123715, -0.07848978, +0.15281130, +0.08364626, +0.09755231, -0.02773284, -0.03952938, +0.13384259, -0.03996222, -0.01055286, -0.00445499, -0.06115851, -0.02286402, -0.07031564, -0.05758839, -0.02276841, + -0.01803347, +0.18275686, +0.00042980, -0.01238341, -0.05145828, +0.05398442, +0.04684926, +0.01635706, -0.04821976, +0.00922990, +0.03454392, +0.05301829, -0.00557295, -0.01839993, +0.04891814, -0.01499163, -0.00400063, +0.00447875, +0.03184761, +0.02414339, -0.03513199, -0.01135147, -0.01462615, + -0.02198793, -0.07285344, -0.00794616, -0.02685598, -0.05406042, +0.14639444, +0.11636605, -0.02015760, -0.07985252, -0.03197371, +0.15878371, -0.05308591, -0.01052404, -0.03003246, -0.00247915, -0.02846799, -0.00336956, +0.00044344, +0.14363135, +0.10875068, -0.05240191, -0.01535184, -0.00852597, + -0.01879784, -0.06459481, +0.00101531, -0.01645397, -0.03805768, -0.00466798, +0.13070912, +0.00069703, -0.07835129, -0.00780449, +0.02192855, +0.04755369, -0.00494381, -0.02134493, +0.01866340, -0.01942652, -0.00086483, +0.00452636, +0.17277759, +0.14926243, -0.03859552, -0.00581398, -0.00585413, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + -0.00057783, +0.00934081, +0.10567109, -0.13183188, +0.02102077, -0.15423587, +0.00369806, +0.00120687, +0.00704451, +0.00355298, +0.00577147, -0.00757835, +0.00194114, +0.01385123, -0.06140362, +0.01886468, -0.15634128, -0.13891543, +0.01326788, +0.02559783, +0.12074324, +0.03624563, +0.09657207, + -0.00596814, +0.02131719, -0.05447449, +0.15632578, +0.01014653, -0.00297623, +0.00606711, +0.00989130, +0.01707366, +0.01205797, +0.00708100, -0.00010464, -0.00427861, +0.01911320, +0.02535905, +0.00055010, -0.02017254, -0.02656369, +0.00834420, +0.00329525, -0.01608867, -0.00965563, -0.04087919, + -0.09411772, -0.01457893, -0.09351218, -0.08935645, -0.07348070, +0.12405542, -0.01787757, -0.01032875, -0.02804962, -0.00845077, -0.01396356, -0.02634182, +0.05797780, -0.02840393, +0.00586776, +0.11010957, -0.03670833, -0.04305913, -0.02731527, -0.04048554, +0.14349876, +0.14199400, -0.06366944, + +0.00633809, +0.02413809, -0.04837505, +0.01219366, +0.02755932, +0.17441340, +0.00739605, +0.00462925, -0.07746250, +0.00442636, +0.00356876, +0.00194076, +0.00797636, +0.02156198, -0.02793161, +0.02501356, -0.01124672, -0.02038247, -0.00544213, -0.02503490, +0.12982413, +0.01453502, -0.03417024, + +0.15399813, +0.02192111, -0.05479140, -0.00268885, -0.00468070, +0.00789275, -0.00893644, +0.00477024, +0.03918486, +0.00535099, +0.00230339, -0.01242338, -0.01203643, +0.11752694, -0.02756864, -0.02404454, -0.01258268, -0.02822548, +0.00635952, -0.00130467, +0.05297544, -0.02873175, -0.04117884, + -0.06284727, +0.01830797, -0.01875022, -0.03450992, +0.12785541, +0.01037399, +0.00471379, +0.12123715, -0.07848978, +0.15281130, +0.08364626, +0.09755231, -0.02773284, -0.03952938, +0.13384259, -0.03996222, -0.01055286, -0.00445499, -0.06115851, -0.02286402, -0.07031564, -0.05758839, -0.02276841, + -0.01803347, +0.18275686, +0.00042980, -0.01238341, -0.05145828, +0.05398442, +0.04684926, +0.01635706, -0.04821976, +0.00922990, +0.03454392, +0.05301829, -0.00557295, -0.01839993, +0.04891814, -0.01499163, -0.00400063, +0.00447875, +0.03184761, +0.02414339, -0.03513199, -0.01135147, -0.01462615, + -0.01550826, -0.04898838, +0.00218605, -0.01053593, -0.03498427, +0.06222895, +0.04980916, +0.05000781, -0.04350490, +0.06008978, +0.03705485, +0.05545657, -0.00214927, -0.01482417, +0.05211715, -0.01147964, +0.00243060, +0.00491710, +0.03736094, +0.03930874, -0.02991660, -0.00326326, -0.00008492, + -0.01879784, -0.06459481, +0.00101531, -0.01645397, -0.03805768, -0.00466798, +0.13070912, +0.00069703, -0.07835129, -0.00780449, +0.02192855, +0.04755369, -0.00494381, -0.02134493, +0.01866340, -0.01942652, -0.00086483, +0.00452636, +0.17277759, +0.14926243, -0.03859552, -0.00581398, -0.00585413, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + -0.02491914, +0.00360196, +0.04877963, -0.01007974, -0.02187387, +0.00401944, +0.00796610, +0.00290476, +0.02085443, +0.00363748, -0.00248994, -0.00713254, +0.56506674, -0.00370003, -0.08933392, -0.14517422, -0.06682019, -0.06426867, +0.00217800, -0.00017151, -0.20843935, -0.34636616, +0.05479635, + +0.00647239, +0.02612098, -0.04922279, +0.01826320, +0.02801275, +0.01276999, +0.01010051, +0.01230147, +0.04533969, +0.01410236, +0.00844802, +0.00264464, +0.00765502, +0.02296686, -0.08447676, +0.02226699, -0.00969485, -0.02021213, +0.01199158, +0.00694759, +0.10984596, +0.01829414, -0.03528082, + -0.04042245, -0.09247672, -0.05153275, +0.00781912, +0.02370364, +0.01250413, -0.00710302, +0.02312764, +0.04356958, +0.03232636, +0.00433750, +0.00295431, +0.00122136, +0.14276875, -0.02524205, +0.01029539, -0.00907253, -0.02657579, +0.01049605, +0.00708700, +0.06299424, -0.00085962, -0.03317496, + +0.16451352, -0.05289310, -0.01376501, -0.02882971, -0.05403575, -0.06761200, -0.05521109, +0.06825307, +0.06212907, +0.08546922, -0.09733928, +0.13090238, -0.02434002, -0.03863623, +0.11231508, -0.06475020, -0.02054697, -0.01012042, +0.10218928, -0.08431031, -0.17624752, -0.03737194, -0.02225051, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + -0.01452142, -0.00430970, +0.04423652, +0.00030702, -0.00465681, -0.00354453, -0.00955817, -0.01146240, +0.00277608, -0.01155343, -0.00294877, -0.01138099, -0.01144859, -0.00090835, -0.10553252, -0.00265750, -0.08254550, -0.07488028, -0.00866185, -0.01125700, +0.08614999, -0.00426749, +0.03985199, + -0.00250888, -0.00778021, -0.05945176, -0.00704065, -0.00884110, -0.00305924, -0.00588574, -0.00410500, -0.00076526, -0.00471276, -0.00272716, -0.00095050, -0.00146849, -0.01024079, -0.02497383, -0.00639215, +0.07591474, +0.06611660, -0.00333065, -0.00224118, -0.00249786, -0.01104749, -0.05517682, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + -0.01810234, -0.01433848, -0.01556876, -0.01265466, -0.01391571, -0.01454221, -0.01361285, -0.01720067, -0.04572617, -0.01769885, -0.00588713, -0.01293452, -0.01413625, -0.01185478, +0.00347981, -0.01715230, +0.01470732, +0.00372905, -0.01439450, -0.01440496, -0.02081138, -0.01808364, -0.01685830, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + -0.00845317, +0.00668586, +0.05765258, +0.15335129, -0.00725228, -0.00388606, +0.00536336, +0.00365117, -0.00169181, +0.00434539, +0.00168581, -0.00102443, -0.00888937, +0.00737656, +0.02320724, -0.00666063, -0.07625187, -0.06794867, +0.00275199, -0.00008282, -0.01748099, -0.01393975, +0.05450763, + -0.00596814, +0.02131719, -0.05447449, +0.15632578, +0.01014653, -0.00297623, +0.00606711, +0.00989130, +0.01707366, +0.01205797, +0.00708100, -0.00010464, -0.00427861, +0.01911320, +0.02535905, +0.00055010, -0.02017254, -0.02656369, +0.00834420, +0.00329525, -0.01608867, -0.00965563, -0.04087919, + -0.09411772, -0.01457893, -0.09351218, -0.08935645, -0.07348070, +0.12405542, -0.01787757, -0.01032875, -0.02804962, -0.00845077, -0.01396356, -0.02634182, +0.05797780, -0.02840393, +0.00586776, +0.11010957, -0.03670833, -0.04305913, -0.02731527, -0.04048554, +0.14349876, +0.14199400, -0.06366944, + +0.13543975, +0.12200954, -0.06121995, -0.01937411, +0.20217113, -0.04385120, +0.08156606, -0.03274667, +0.00159948, -0.04472071, -0.01187587, -0.02447675, -0.02706412, +0.10727713, -0.05091630, -0.03483146, -0.01825676, -0.03006336, -0.05284204, +0.13656417, +0.03637327, -0.07068599, -0.05323033, + +0.15399813, +0.02192111, -0.05479140, -0.00268885, -0.00468070, +0.00789275, -0.00893644, +0.00477024, +0.03918486, +0.00535099, +0.00230339, -0.01242338, -0.01203643, +0.11752694, -0.02756864, -0.02404454, -0.01258268, -0.02822548, +0.00635952, -0.00130467, +0.05297544, -0.02873175, -0.04117884, + -0.06284727, +0.01830797, -0.01875022, -0.03450992, +0.12785541, +0.01037399, +0.00471379, +0.12123715, -0.07848978, +0.15281130, +0.08364626, +0.09755231, -0.02773284, -0.03952938, +0.13384259, -0.03996222, -0.01055286, -0.00445499, -0.06115851, -0.02286402, -0.07031564, -0.05758839, -0.02276841, + -0.01803347, +0.18275686, +0.00042980, -0.01238341, -0.05145828, +0.05398442, +0.04684926, +0.01635706, -0.04821976, +0.00922990, +0.03454392, +0.05301829, -0.00557295, -0.01839993, +0.04891814, -0.01499163, -0.00400063, +0.00447875, +0.03184761, +0.02414339, -0.03513199, -0.01135147, -0.01462615, + -0.02198793, -0.07285344, -0.00794616, -0.02685598, -0.05406042, +0.14639444, +0.11636605, -0.02015760, -0.07985252, -0.03197371, +0.15878371, -0.05308591, -0.01052404, -0.03003246, -0.00247915, -0.02846799, -0.00336956, +0.00044344, +0.14363135, +0.10875068, -0.05240191, -0.01535184, -0.00852597, + -0.01879784, -0.06459481, +0.00101531, -0.01645397, -0.03805768, -0.00466798, +0.13070912, +0.00069703, -0.07835129, -0.00780449, +0.02192855, +0.04755369, -0.00494381, -0.02134493, +0.01866340, -0.01942652, -0.00086483, +0.00452636, +0.17277759, +0.14926243, -0.03859552, -0.00581398, -0.00585413, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + -0.00057783, +0.00934081, +0.10567109, -0.13183188, +0.02102077, -0.15423587, +0.00369806, +0.00120687, +0.00704451, +0.00355298, +0.00577147, -0.00757835, +0.00194114, +0.01385123, -0.06140362, +0.01886468, -0.15634128, -0.13891543, +0.01326788, +0.02559783, +0.12074324, +0.03624563, +0.09657207, + -0.00596814, +0.02131719, -0.05447449, +0.15632578, +0.01014653, -0.00297623, +0.00606711, +0.00989130, +0.01707366, +0.01205797, +0.00708100, -0.00010464, -0.00427861, +0.01911320, +0.02535905, +0.00055010, -0.02017254, -0.02656369, +0.00834420, +0.00329525, -0.01608867, -0.00965563, -0.04087919, + -0.09411772, -0.01457893, -0.09351218, -0.08935645, -0.07348070, +0.12405542, -0.01787757, -0.01032875, -0.02804962, -0.00845077, -0.01396356, -0.02634182, +0.05797780, -0.02840393, +0.00586776, +0.11010957, -0.03670833, -0.04305913, -0.02731527, -0.04048554, +0.14349876, +0.14199400, -0.06366944, + +0.00633809, +0.02413809, -0.04837505, +0.01219366, +0.02755932, +0.17441340, +0.00739605, +0.00462925, -0.07746250, +0.00442636, +0.00356876, +0.00194076, +0.00797636, +0.02156198, -0.02793161, +0.02501356, -0.01124672, -0.02038247, -0.00544213, -0.02503490, +0.12982413, +0.01453502, -0.03417024, + +0.15399813, +0.02192111, -0.05479140, -0.00268885, -0.00468070, +0.00789275, -0.00893644, +0.00477024, +0.03918486, +0.00535099, +0.00230339, -0.01242338, -0.01203643, +0.11752694, -0.02756864, -0.02404454, -0.01258268, -0.02822548, +0.00635952, -0.00130467, +0.05297544, -0.02873175, -0.04117884, + -0.06284727, +0.01830797, -0.01875022, -0.03450992, +0.12785541, +0.01037399, +0.00471379, +0.12123715, -0.07848978, +0.15281130, +0.08364626, +0.09755231, -0.02773284, -0.03952938, +0.13384259, -0.03996222, -0.01055286, -0.00445499, -0.06115851, -0.02286402, -0.07031564, -0.05758839, -0.02276841, + -0.01803347, +0.18275686, +0.00042980, -0.01238341, -0.05145828, +0.05398442, +0.04684926, +0.01635706, -0.04821976, +0.00922990, +0.03454392, +0.05301829, -0.00557295, -0.01839993, +0.04891814, -0.01499163, -0.00400063, +0.00447875, +0.03184761, +0.02414339, -0.03513199, -0.01135147, -0.01462615, + -0.01550826, -0.04898838, +0.00218605, -0.01053593, -0.03498427, +0.06222895, +0.04980916, +0.05000781, -0.04350490, +0.06008978, +0.03705485, +0.05545657, -0.00214927, -0.01482417, +0.05211715, -0.01147964, +0.00243060, +0.00491710, +0.03736094, +0.03930874, -0.02991660, -0.00326326, -0.00008492, + -0.01879784, -0.06459481, +0.00101531, -0.01645397, -0.03805768, -0.00466798, +0.13070912, +0.00069703, -0.07835129, -0.00780449, +0.02192855, +0.04755369, -0.00494381, -0.02134493, +0.01866340, -0.01942652, -0.00086483, +0.00452636, +0.17277759, +0.14926243, -0.03859552, -0.00581398, -0.00585413, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + -0.02491914, +0.00360196, +0.04877963, -0.01007974, -0.02187387, +0.00401944, +0.00796610, +0.00290476, +0.02085443, +0.00363748, -0.00248994, -0.00713254, +0.56506674, -0.00370003, -0.08933392, -0.14517422, -0.06682019, -0.06426867, +0.00217800, -0.00017151, -0.20843935, -0.34636616, +0.05479635, + +0.00647239, +0.02612098, -0.04922279, +0.01826320, +0.02801275, +0.01276999, +0.01010051, +0.01230147, +0.04533969, +0.01410236, +0.00844802, +0.00264464, +0.00765502, +0.02296686, -0.08447676, +0.02226699, -0.00969485, -0.02021213, +0.01199158, +0.00694759, +0.10984596, +0.01829414, -0.03528082, + -0.04042245, -0.09247672, -0.05153275, +0.00781912, +0.02370364, +0.01250413, -0.00710302, +0.02312764, +0.04356958, +0.03232636, +0.00433750, +0.00295431, +0.00122136, +0.14276875, -0.02524205, +0.01029539, -0.00907253, -0.02657579, +0.01049605, +0.00708700, +0.06299424, -0.00085962, -0.03317496, + +0.16451352, -0.05289310, -0.01376501, -0.02882971, -0.05403575, -0.06761200, -0.05521109, +0.06825307, +0.06212907, +0.08546922, -0.09733928, +0.13090238, -0.02434002, -0.03863623, +0.11231508, -0.06475020, -0.02054697, -0.01012042, +0.10218928, -0.08431031, -0.17624752, -0.03737194, -0.02225051, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + -0.01463467, -0.00347654, +0.04427984, +0.00107819, -0.00347955, +0.00043642, -0.00854392, -0.01101576, -0.00268171, -0.01115525, -0.00286472, -0.01114779, -0.01157564, -0.00094351, -0.08665046, -0.00444702, -0.08240551, -0.07482202, -0.00831173, -0.01108164, +0.06808998, -0.00487948, +0.03989804, + -0.00250888, -0.00778021, -0.05945176, -0.00704065, -0.00884110, -0.00305924, -0.00588574, -0.00410500, -0.00076526, -0.00471276, -0.00272716, -0.00095050, -0.00146849, -0.01024079, -0.02497383, -0.00639215, +0.07591474, +0.06611660, -0.00333065, -0.00224118, -0.00249786, -0.01104749, -0.05517682, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + -0.01810234, -0.01433848, -0.01556876, -0.01265466, -0.01391571, -0.01454221, -0.01361285, -0.01720067, -0.04572617, -0.01769885, -0.00588713, -0.01293452, -0.01413625, -0.01185478, +0.00347981, -0.01715230, +0.01470732, +0.00372905, -0.01439450, -0.01440496, -0.02081138, -0.01808364, -0.01685830, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + -0.00069107, +0.01017397, +0.10571441, -0.13106071, +0.02219803, -0.15025492, +0.00471231, +0.00165351, +0.00158672, +0.00395115, +0.00585551, -0.00734516, +0.00181408, +0.01381607, -0.04252155, +0.01707516, -0.15620129, -0.13885717, +0.01361799, +0.02577319, +0.10268322, +0.03563364, +0.09661812, + +0.00499390, +0.02241154, -0.05267530, +0.01001513, +0.02623991, +0.00396908, +0.00658949, +0.01034513, +0.01953073, +0.01242534, +0.00812235, +0.00187029, +0.00607925, +0.02197743, +0.02712564, +0.01360287, -0.01983541, -0.02473162, +0.00892286, +0.00561925, +0.00389018, +0.01533162, -0.04020999, + -0.00780606, +0.01199864, -0.05815394, +0.14017544, +0.00645334, +0.14493780, -0.00530627, -0.00062211, -0.00432363, -0.00004349, +0.00171957, -0.00198940, -0.00729071, +0.01650436, +0.10069089, -0.00840176, -0.03223493, -0.03139081, -0.01309506, -0.03049810, -0.11610097, -0.01648453, -0.04672848, + -0.07624231, +0.11849259, -0.08232754, -0.05530002, -0.29376688, -0.01842197, -0.00405532, -0.01283379, +0.01801611, -0.01818661, -0.00624755, -0.01708591, +0.07244137, -0.02246362, -0.18193549, +0.13352686, -0.01721661, -0.03250473, -0.00489767, -0.01153826, +0.35322569, +0.18351069, -0.05844438, + +0.02378173, -0.08195452, -0.04233917, +0.03160143, -0.17979853, +0.02257872, +0.01715616, +0.03186228, -0.07829985, +0.04219637, +0.01314438, +0.01208626, +0.02271206, +0.02909917, +0.01066895, +0.03461462, -0.00560488, -0.01842870, +0.01635134, +0.01642103, +0.13285490, +0.05821489, -0.02426230, + +0.13731148, -0.14812607, -0.06519391, -0.00802753, -0.26111630, -0.09313672, +0.03269215, +0.06493399, -0.03441332, +0.08566575, +0.04301630, +0.04030604, -0.01406989, +0.09806624, +0.06312719, -0.04542641, -0.02114157, -0.03457950, +0.05080282, +0.06480884, -0.01427406, -0.00720463, -0.05156379, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + -0.00069107, +0.01017397, +0.10571441, -0.13106071, +0.02219803, -0.15025492, +0.00471231, +0.00165351, +0.00158672, +0.00395115, +0.00585551, -0.00734516, +0.00181408, +0.01381607, -0.04252155, +0.01707516, -0.15620129, -0.13885717, +0.01361799, +0.02577319, +0.10268322, +0.03563364, +0.09661812, + +0.00499390, +0.02241154, -0.05267530, +0.01001513, +0.02623991, +0.00396908, +0.00658949, +0.01034513, +0.01953073, +0.01242534, +0.00812235, +0.00187029, +0.00607925, +0.02197743, +0.02712564, +0.01360287, -0.01983541, -0.02473162, +0.00892286, +0.00561925, +0.00389018, +0.01533162, -0.04020999, + -0.00780606, +0.01199864, -0.05815394, +0.14017544, +0.00645334, +0.14493780, -0.00530627, -0.00062211, -0.00432363, -0.00004349, +0.00171957, -0.00198940, -0.00729071, +0.01650436, +0.10069089, -0.00840176, -0.03223493, -0.03139081, -0.01309506, -0.03049810, -0.11610097, -0.01648453, -0.04672848, + -0.07624231, +0.11849259, -0.08232754, -0.05530002, -0.29376688, -0.01842197, -0.00405532, -0.01283379, +0.01801611, -0.01818661, -0.00624755, -0.01708591, +0.07244137, -0.02246362, -0.18193549, +0.13352686, -0.01721661, -0.03250473, -0.00489767, -0.01153826, +0.35322569, +0.18351069, -0.05844438, + +0.02378173, -0.08195452, -0.04233917, +0.03160143, -0.17979853, +0.02257872, +0.01715616, +0.03186228, -0.07829985, +0.04219637, +0.01314438, +0.01208626, +0.02271206, +0.02909917, +0.01066895, +0.03461462, -0.00560488, -0.01842870, +0.01635134, +0.01642103, +0.13285490, +0.05821489, -0.02426230, + +0.13731148, -0.14812607, -0.06519391, -0.00802753, -0.26111630, -0.09313672, +0.03269215, +0.06493399, -0.03441332, +0.08566575, +0.04301630, +0.04030604, -0.01406989, +0.09806624, +0.06312719, -0.04542641, -0.02114157, -0.03457950, +0.05080282, +0.06480884, -0.01427406, -0.00720463, -0.05156379, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + -0.02503238, +0.00443512, +0.04882295, -0.00930857, -0.02069661, +0.00800039, +0.00898036, +0.00335140, +0.01539665, +0.00403566, -0.00240589, -0.00689934, +0.56493968, -0.00373519, -0.07045186, -0.14696374, -0.06668020, -0.06421041, +0.00252812, +0.00000384, -0.22649936, -0.34697815, +0.05484240, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + -0.04053569, -0.09164356, -0.05148944, +0.00859029, +0.02488090, +0.01648507, -0.00608877, +0.02357428, +0.03811180, +0.03272453, +0.00442155, +0.00318751, +0.00109431, +0.14273360, -0.00635999, +0.00850587, -0.00893254, -0.02651752, +0.01084616, +0.00726236, +0.04493422, -0.00147161, -0.03312891, + +0.16943546, -0.04813508, -0.00627938, -0.01894547, -0.04751800, -0.06312675, -0.05308992, +0.06934691, -0.11365719, +0.08630842, -0.09607357, +0.13268016, -0.00613831, -0.03639683, +0.19373335, -0.03723602, -0.00699818, -0.00198260, +0.10467543, -0.08292932, -0.16057431, -0.01422795, -0.01693542, + +0.00460587, +0.00305429, +0.00515891, +0.00690762, +0.00547482, +0.00270465, +0.00119205, +0.00076920, -0.08280237, +0.00059631, +0.00116273, +0.00162874, +0.01779624, +0.00195317, +0.04108136, +0.02661760, +0.00694430, +0.00493647, +0.00181257, +0.00095888, -0.03652825, +0.02280916, +0.00306681, + -0.00573899, +0.00092830, +0.05227095, +0.01191682, +0.00642717, +0.00406511, -0.00708893, -0.00980199, -0.07530256, -0.01020552, -0.00064225, -0.00803936, +0.02361136, +0.00267661, -0.04482463, +0.04789161, -0.07512141, -0.06815044, -0.00536016, -0.00958597, -0.05716797, +0.04040400, +0.04378336, + +0.00209700, -0.00472593, -0.05429285, -0.00013302, -0.00336628, -0.00035460, -0.00469369, -0.00333580, -0.08356763, -0.00411645, -0.00156443, +0.00067824, +0.01632775, -0.00828762, +0.01610754, +0.02022546, +0.08285904, +0.07105306, -0.00151807, -0.00128230, -0.03902611, +0.01176166, -0.05211002, + +0.00460587, +0.00305429, +0.00515891, +0.00690762, +0.00547482, +0.00270465, +0.00119205, +0.00076920, -0.08280237, +0.00059631, +0.00116273, +0.00162874, +0.01779624, +0.00195317, +0.04108136, +0.02661760, +0.00694430, +0.00493647, +0.00181257, +0.00095888, -0.03652825, +0.02280916, +0.00306681, + -0.00889059, -0.00822991, -0.00525094, +0.00116059, -0.00296606, -0.00913292, -0.01122874, -0.01566227, -0.21133091, -0.01650622, -0.00356168, -0.00967705, +0.02145622, -0.00794844, +0.08564254, +0.03608290, +0.02859591, +0.01360198, -0.01076935, -0.01248719, -0.09386787, +0.02753468, -0.01072469, + +0.00460587, +0.00305429, +0.00515891, +0.00690762, +0.00547482, +0.00270465, +0.00119205, +0.00076920, -0.08280237, +0.00059631, +0.00116273, +0.00162874, +0.01779624, +0.00195317, +0.04108136, +0.02661760, +0.00694430, +0.00493647, +0.00181257, +0.00095888, -0.03652825, +0.02280916, +0.00306681, + +0.00460587, +0.00305429, +0.00515891, +0.00690762, +0.00547482, +0.00270465, +0.00119205, +0.00076920, -0.08280237, +0.00059631, +0.00116273, +0.00162874, +0.01779624, +0.00195317, +0.04108136, +0.02661760, +0.00694430, +0.00493647, +0.00181257, +0.00095888, -0.03652825, +0.02280916, +0.00306681, + +0.00460587, +0.00305429, +0.00515891, +0.00690762, +0.00547482, +0.00270465, +0.00119205, +0.00076920, -0.08280237, +0.00059631, +0.00116273, +0.00162874, +0.01779624, +0.00195317, +0.04108136, +0.02661760, +0.00694430, +0.00493647, +0.00181257, +0.00095888, -0.03652825, +0.02280916, +0.00306681, + +0.00460587, +0.00305429, +0.00515891, +0.00690762, +0.00547482, +0.00270465, +0.00119205, +0.00076920, -0.08280237, +0.00059631, +0.00116273, +0.00162874, +0.01779624, +0.00195317, +0.04108136, +0.02661760, +0.00694430, +0.00493647, +0.00181257, +0.00095888, -0.03652825, +0.02280916, +0.00306681, + +0.00460587, +0.00305429, +0.00515891, +0.00690762, +0.00547482, +0.00270465, +0.00119205, +0.00076920, -0.08280237, +0.00059631, +0.00116273, +0.00162874, +0.01779624, +0.00195317, +0.04108136, +0.02661760, +0.00694430, +0.00493647, +0.00181257, +0.00095888, -0.03652825, +0.02280916, +0.00306681, + +0.00460587, +0.00305429, +0.00515891, +0.00690762, +0.00547482, +0.00270465, +0.00119205, +0.00076920, -0.08280237, +0.00059631, +0.00116273, +0.00162874, +0.01779624, +0.00195317, +0.04108136, +0.02661760, +0.00694430, +0.00493647, +0.00181257, +0.00095888, -0.03652825, +0.02280916, +0.00306681, + +0.00460587, +0.00305429, +0.00515891, +0.00690762, +0.00547482, +0.00270465, +0.00119205, +0.00076920, -0.08280237, +0.00059631, +0.00116273, +0.00162874, +0.01779624, +0.00195317, +0.04108136, +0.02661760, +0.00694430, +0.00493647, +0.00181257, +0.00095888, -0.03652825, +0.02280916, +0.00306681, + -0.00384729, +0.00974014, +0.06281149, +0.16025892, -0.00177746, -0.00118142, +0.00655541, +0.00442037, -0.08449418, +0.00494170, +0.00284853, +0.00060431, +0.00890686, +0.00932974, +0.06428860, +0.01995698, -0.06930757, -0.06301221, +0.00456457, +0.00087606, -0.05400924, +0.00886941, +0.05757443, + -0.00136227, +0.02437147, -0.04931558, +0.16323340, +0.01562135, -0.00027158, +0.00725916, +0.01066050, -0.06572871, +0.01265428, +0.00824373, +0.00152410, +0.01351762, +0.02106638, +0.06644042, +0.02716770, -0.01322824, -0.02162723, +0.01015678, +0.00425413, -0.05261692, +0.01315353, -0.03781238, + -0.08479272, -0.00930352, -0.08323768, -0.07631237, -0.06370831, +0.12548376, -0.01650772, -0.00923699, -0.18819658, -0.00765632, -0.01172215, -0.02331754, +0.09369733, -0.02446243, +0.06914842, +0.16513430, -0.02295973, -0.03324446, -0.02404023, -0.03874313, +0.08850228, +0.18822430, -0.05758188, + +0.13961631, +0.12419326, -0.05834444, -0.01467193, +0.20778029, -0.03894621, +0.08284325, -0.03185546, +0.00632321, -0.04396911, -0.01073208, -0.02276385, -0.00980042, +0.10890893, -0.03128977, -0.01089995, -0.01777696, -0.02827000, -0.05135293, +0.13727630, -0.07041645, -0.04882366, -0.05236576, + +0.15817469, +0.02410483, -0.05191589, +0.00201333, +0.00092846, +0.01279775, -0.00765925, +0.00566144, +0.04390859, +0.00610259, +0.00344718, -0.01071049, +0.00522728, +0.11915873, -0.00794211, -0.00011303, -0.01210288, -0.02643211, +0.00784863, -0.00059253, -0.05381428, -0.00686942, -0.04031427, + -0.06307377, +0.01997430, -0.01866358, -0.03296759, +0.13020992, +0.01833589, +0.00674230, +0.12213043, -0.08940535, +0.15360766, +0.08381436, +0.09801870, -0.02798696, -0.03959969, +0.17160672, -0.04354126, -0.01027287, -0.00433846, -0.06045829, -0.02251331, -0.10643567, -0.05881238, -0.02267631, + -0.01814672, +0.18359002, +0.00047312, -0.01161224, -0.05028102, +0.05796537, +0.04786352, +0.01680370, -0.05367754, +0.00962808, +0.03462797, +0.05325148, -0.00570001, -0.01843508, +0.06780021, -0.01678115, -0.00386064, +0.00453701, +0.03219772, +0.02431875, -0.05319201, -0.01196346, -0.01458010, + -0.02210117, -0.07202028, -0.00790284, -0.02608481, -0.05288317, +0.15037539, +0.11738031, -0.01971096, -0.08531030, -0.03157554, +0.15886776, -0.05285272, -0.01065110, -0.03006762, +0.01640291, -0.03025751, -0.00322957, +0.00050170, +0.14398146, +0.10892604, -0.07046192, -0.01596383, -0.00847992, + -0.01891109, -0.06376165, +0.00105863, -0.01568280, -0.03688042, -0.00068703, +0.13172338, +0.00114367, -0.08380907, -0.00740631, +0.02201260, +0.04778689, -0.00507087, -0.02138008, +0.03754547, -0.02121604, -0.00072484, +0.00458462, +0.17312770, +0.14943778, -0.05665554, -0.00642598, -0.00580808, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.00820460, +0.01457881, +0.11370552, -0.12022208, +0.03210475, -0.14662623, +0.00616730, +0.00286727, -0.07103413, +0.00490089, +0.00807798, -0.00423672, +0.03700109, +0.01743619, -0.00069572, +0.06941379, -0.14891719, -0.13218560, +0.01656957, +0.02726885, -0.02257472, +0.08091712, +0.10050344, + -0.00136227, +0.02437147, -0.04931558, +0.16323340, +0.01562135, -0.00027158, +0.00725916, +0.01066050, -0.06572871, +0.01265428, +0.00824373, +0.00152410, +0.01351762, +0.02106638, +0.06644042, +0.02716770, -0.01322824, -0.02162723, +0.01015678, +0.00425413, -0.05261692, +0.01315353, -0.03781238, + -0.08479272, -0.00930352, -0.08323768, -0.07631237, -0.06370831, +0.12548376, -0.01650772, -0.00923699, -0.18819658, -0.00765632, -0.01172215, -0.02331754, +0.09369733, -0.02446243, +0.06914842, +0.16513430, -0.02295973, -0.03324446, -0.02404023, -0.03874313, +0.08850228, +0.18822430, -0.05758188, + +0.01051464, +0.02632180, -0.04549953, +0.01689583, +0.03316848, +0.17931840, +0.00867324, +0.00552045, -0.07273876, +0.00517796, +0.00471255, +0.00365365, +0.02524007, +0.02319377, -0.00830509, +0.04894507, -0.01076692, -0.01858911, -0.00395302, -0.02432276, +0.02303442, +0.03639735, -0.03330566, + +0.15817469, +0.02410483, -0.05191589, +0.00201333, +0.00092846, +0.01279775, -0.00765925, +0.00566144, +0.04390859, +0.00610259, +0.00344718, -0.01071049, +0.00522728, +0.11915873, -0.00794211, -0.00011303, -0.01210288, -0.02643211, +0.00784863, -0.00059253, -0.05381428, -0.00686942, -0.04031427, + -0.06307377, +0.01997430, -0.01866358, -0.03296759, +0.13020992, +0.01833589, +0.00674230, +0.12213043, -0.08940535, +0.15360766, +0.08381436, +0.09801870, -0.02798696, -0.03959969, +0.17160672, -0.04354126, -0.01027287, -0.00433846, -0.06045829, -0.02251331, -0.10643567, -0.05881238, -0.02267631, + -0.01814672, +0.18359002, +0.00047312, -0.01161224, -0.05028102, +0.05796537, +0.04786352, +0.01680370, -0.05367754, +0.00962808, +0.03462797, +0.05325148, -0.00570001, -0.01843508, +0.06780021, -0.01678115, -0.00386064, +0.00453701, +0.03219772, +0.02431875, -0.05319201, -0.01196346, -0.01458010, + -0.01562151, -0.04815521, +0.00222937, -0.00976477, -0.03380701, +0.06620990, +0.05082342, +0.05045445, -0.04896269, +0.06048795, +0.03713889, +0.05568977, -0.00227633, -0.01485932, +0.07099922, -0.01326916, +0.00257059, +0.00497536, +0.03771105, +0.03948409, -0.04797661, -0.00387525, -0.00003887, + -0.01891109, -0.06376165, +0.00105863, -0.01568280, -0.03688042, -0.00068703, +0.13172338, +0.00114367, -0.08380907, -0.00740631, +0.02201260, +0.04778689, -0.00507087, -0.02138008, +0.03754547, -0.02121604, -0.00072484, +0.00458462, +0.17312770, +0.14943778, -0.05665554, -0.00642598, -0.00580808, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + -0.02074258, +0.00578568, +0.05165515, -0.00537757, -0.01626471, +0.00892444, +0.00924329, +0.00379597, +0.02557816, +0.00438908, -0.00134615, -0.00541965, +0.58233045, -0.00206824, -0.06970740, -0.12124272, -0.06634039, -0.06247530, +0.00366712, +0.00054063, -0.31522906, -0.32450383, +0.05566092, + +0.01064895, +0.02830470, -0.04634728, +0.02296537, +0.03362191, +0.01767499, +0.01137770, +0.01319267, +0.05006342, +0.01485396, +0.00959180, +0.00435754, +0.02491873, +0.02459865, -0.06485023, +0.04619849, -0.00921506, -0.01841877, +0.01348070, +0.00765973, +0.00305625, +0.04015647, -0.03441624, + -0.03624589, -0.09029301, -0.04865724, +0.01252129, +0.02931280, +0.01740912, -0.00582583, +0.02401885, +0.04829331, +0.03307796, +0.00548129, +0.00466720, +0.01848507, +0.14440054, -0.00561553, +0.03422690, -0.00859273, -0.02478242, +0.01198516, +0.00779914, -0.04379548, +0.02100271, -0.03231039, + +0.16550714, -0.04828953, -0.00871936, -0.02066321, -0.05123222, -0.06226573, -0.05152667, +0.06925556, -0.03132891, +0.08623369, -0.09696941, +0.13129729, -0.02233513, -0.03740068, +0.20277468, -0.06039539, -0.00676258, -0.00355433, +0.10411272, -0.08275558, -0.15109778, -0.03542252, -0.01681143, + +0.00067755, +0.00289983, +0.00271893, +0.00518988, +0.00176061, +0.00356567, +0.00275531, +0.00067785, -0.00047409, +0.00052159, +0.00026689, +0.00024586, +0.00159942, +0.00094933, +0.05012270, +0.00345823, +0.00717990, +0.00336474, +0.00124987, +0.00113262, -0.02705171, +0.00161459, +0.00319080, + -0.01047392, +0.00191471, +0.04798495, +0.01305862, +0.00029350, +0.00952184, +0.00681579, -0.00828447, +0.06131028, -0.00885080, -0.00211207, -0.01024898, -0.00744412, +0.00467417, -0.08310759, +0.00601258, -0.07349612, -0.07096262, -0.00396082, -0.00804289, +0.04375068, -0.00086971, +0.04574956, + -0.00418779, -0.00552606, -0.05703970, -0.00445312, -0.00809798, -0.00059174, -0.01211830, -0.00389659, +0.05281329, -0.00457078, -0.00262860, -0.00084249, -0.00054670, -0.01286794, +0.01640869, -0.00412427, +0.08257384, +0.06933862, -0.00306556, -0.00173914, -0.07003821, -0.00963086, -0.05281827, + +0.00067755, +0.00289983, +0.00271893, +0.00518988, +0.00176061, +0.00356567, +0.00275531, +0.00067785, -0.00047409, +0.00052159, +0.00026689, +0.00024586, +0.00159942, +0.00094933, +0.05012270, +0.00345823, +0.00717990, +0.00336474, +0.00124987, +0.00113262, -0.02705171, +0.00161459, +0.00319080, + -0.01439077, -0.00789314, -0.00982402, +0.00032744, -0.00937702, -0.00631269, +0.00088564, -0.01537552, -0.10072697, -0.01627608, -0.00518503, -0.01230494, -0.01025979, -0.00637964, +0.11246540, -0.00904550, +0.02958793, +0.01060124, -0.01090998, -0.01150913, -0.03442616, -0.01465652, -0.00964445, + +0.00067755, +0.00289983, +0.00271893, +0.00518988, +0.00176061, +0.00356567, +0.00275531, +0.00067785, -0.00047409, +0.00052159, +0.00026689, +0.00024586, +0.00159942, +0.00094933, +0.05012270, +0.00345823, +0.00717990, +0.00336474, +0.00124987, +0.00113262, -0.02705171, +0.00161459, +0.00319080, + +0.00067755, +0.00289983, +0.00271893, +0.00518988, +0.00176061, +0.00356567, +0.00275531, +0.00067785, -0.00047409, +0.00052159, +0.00026689, +0.00024586, +0.00159942, +0.00094933, +0.05012270, +0.00345823, +0.00717990, +0.00336474, +0.00124987, +0.00113262, -0.02705171, +0.00161459, +0.00319080, + +0.00067755, +0.00289983, +0.00271893, +0.00518988, +0.00176061, +0.00356567, +0.00275531, +0.00067785, -0.00047409, +0.00052159, +0.00026689, +0.00024586, +0.00159942, +0.00094933, +0.05012270, +0.00345823, +0.00717990, +0.00336474, +0.00124987, +0.00113262, -0.02705171, +0.00161459, +0.00319080, + +0.00067755, +0.00289983, +0.00271893, +0.00518988, +0.00176061, +0.00356567, +0.00275531, +0.00067785, -0.00047409, +0.00052159, +0.00026689, +0.00024586, +0.00159942, +0.00094933, +0.05012270, +0.00345823, +0.00717990, +0.00336474, +0.00124987, +0.00113262, -0.02705171, +0.00161459, +0.00319080, + +0.00067755, +0.00289983, +0.00271893, +0.00518988, +0.00176061, +0.00356567, +0.00275531, +0.00067785, -0.00047409, +0.00052159, +0.00026689, +0.00024586, +0.00159942, +0.00094933, +0.05012270, +0.00345823, +0.00717990, +0.00336474, +0.00124987, +0.00113262, -0.02705171, +0.00161459, +0.00319080, + +0.00067755, +0.00289983, +0.00271893, +0.00518988, +0.00176061, +0.00356567, +0.00275531, +0.00067785, -0.00047409, +0.00052159, +0.00026689, +0.00024586, +0.00159942, +0.00094933, +0.05012270, +0.00345823, +0.00717990, +0.00336474, +0.00124987, +0.00113262, -0.02705171, +0.00161459, +0.00319080, + +0.00067755, +0.00289983, +0.00271893, +0.00518988, +0.00176061, +0.00356567, +0.00275531, +0.00067785, -0.00047409, +0.00052159, +0.00026689, +0.00024586, +0.00159942, +0.00094933, +0.05012270, +0.00345823, +0.00717990, +0.00336474, +0.00124987, +0.00113262, -0.02705171, +0.00161459, +0.00319080, + -0.00541915, +0.01023137, +0.06067838, +0.16114352, -0.00447420, +0.00077779, +0.01710654, +0.00479846, -0.05621853, +0.00524657, +0.00212102, -0.00064071, -0.00661233, +0.01190237, +0.08207012, -0.00201205, -0.06855116, -0.06444122, +0.00498664, +0.00168039, -0.00404406, -0.01212722, +0.05853067, + -0.00293413, +0.02486269, -0.05144868, +0.16411800, +0.01292461, +0.00168762, +0.01781029, +0.01103859, -0.03745306, +0.01295915, +0.00751621, +0.00027908, -0.00200157, +0.02363901, +0.08422194, +0.00519868, -0.01247183, -0.02305624, +0.01057885, +0.00505845, -0.00265174, -0.00784309, -0.03685614, + -0.09105816, -0.00961640, -0.08809784, -0.07912046, -0.07039654, +0.12566750, -0.00618367, -0.01018102, -0.10360153, -0.00855075, -0.01349904, -0.02636372, +0.06132078, -0.02332240, +0.16107709, +0.11675653, -0.02260098, -0.03643376, -0.02572085, -0.03833008, +0.10646707, +0.14511563, -0.05738760, + +0.14116616, +0.12597980, -0.05988359, -0.00921004, +0.20637831, -0.03325234, +0.10417259, -0.02977715, +0.00655513, -0.04216006, -0.01113772, -0.02345273, -0.02398145, +0.11548681, -0.06987388, -0.02842925, -0.01586648, -0.02936773, -0.04840610, +0.13927622, +0.06151431, -0.06870485, -0.04969131, + +0.15972455, +0.02589137, -0.05345503, +0.00747522, -0.00047352, +0.01849162, +0.01367008, +0.00773975, +0.04414052, +0.00791164, +0.00304153, -0.01139937, -0.00895376, +0.12573661, -0.04652622, -0.01764232, -0.01019239, -0.02752984, +0.01079546, +0.00140739, +0.07811648, -0.02675061, -0.03763982, + -0.06154326, +0.02127358, -0.01808941, -0.02901769, +0.13076448, +0.02360887, +0.01032297, +0.12459198, -0.03738755, +0.15585680, +0.08412144, +0.09885526, -0.02666589, -0.03874216, +0.04139509, -0.03704251, -0.00900633, -0.00396133, -0.05737834, -0.02138327, -0.02348181, -0.05697741, -0.02090438, + -0.01738146, +0.18423966, +0.00076020, -0.00963729, -0.05000374, +0.06060186, +0.04965385, +0.01803448, -0.02766864, +0.01075265, +0.03478151, +0.05366977, -0.00503948, -0.01800631, +0.00269439, -0.01353178, -0.00322737, +0.00472558, +0.03373770, +0.02488377, -0.01171508, -0.01104598, -0.01369414, + -0.02133592, -0.07137064, -0.00761576, -0.02410986, -0.05260589, +0.15301188, +0.11917065, -0.01848018, -0.05930141, -0.03045096, +0.15902130, -0.05243444, -0.00999057, -0.02963885, -0.04870290, -0.02700813, -0.00259630, +0.00069026, +0.14552144, +0.10949105, -0.02898499, -0.01504635, -0.00759396, + -0.01814584, -0.06311201, +0.00134572, -0.01370785, -0.03660314, +0.00194946, +0.13351371, +0.00237445, -0.05780018, -0.00628174, +0.02216614, +0.04820517, -0.00441034, -0.02095132, -0.02756035, -0.01796667, -0.00009157, +0.00477318, +0.17466768, +0.15000280, -0.01517861, -0.00550850, -0.00492212, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.00582614, +0.01621089, +0.10972639, -0.11647793, +0.02698855, -0.14007133, +0.02905989, +0.00485424, +0.01152607, +0.00663521, +0.00677649, -0.00630848, +0.00662323, +0.02301023, -0.03023850, +0.02872512, -0.14677110, -0.13485506, +0.01895369, +0.02944251, +0.11883257, +0.03984136, +0.10330189, + -0.00293413, +0.02486269, -0.05144868, +0.16411800, +0.01292461, +0.00168762, +0.01781029, +0.01103859, -0.03745306, +0.01295915, +0.00751621, +0.00027908, -0.00200157, +0.02363901, +0.08422194, +0.00519868, -0.01247183, -0.02305624, +0.01057885, +0.00505845, -0.00265174, -0.00784309, -0.03685614, + -0.09105816, -0.00961640, -0.08809784, -0.07912046, -0.07039654, +0.12566750, -0.00618367, -0.01018102, -0.10360153, -0.00855075, -0.01349904, -0.02636372, +0.06132078, -0.02332240, +0.16107709, +0.11675653, -0.02260098, -0.03643376, -0.02572085, -0.03833008, +0.10646707, +0.14511563, -0.05738760, + +0.00970804, +0.02746266, -0.04734555, +0.01975538, +0.03074902, +0.18391409, +0.02101471, +0.00712932, -0.01845421, +0.00660740, +0.00413858, +0.00282691, +0.01038140, +0.02619517, -0.05562938, +0.03022542, -0.00937724, -0.01982955, -0.00199097, -0.02295342, +0.11447653, +0.01631821, -0.03146346, + +0.15972455, +0.02589137, -0.05345503, +0.00747522, -0.00047352, +0.01849162, +0.01367008, +0.00773975, +0.04414052, +0.00791164, +0.00304153, -0.01139937, -0.00895376, +0.12573661, -0.04652622, -0.01764232, -0.01019239, -0.02752984, +0.01079546, +0.00140739, +0.07811648, -0.02675061, -0.03763982, + -0.06154326, +0.02127358, -0.01808941, -0.02901769, +0.13076448, +0.02360887, +0.01032297, +0.12459198, -0.03738755, +0.15585680, +0.08412144, +0.09885526, -0.02666589, -0.03874216, +0.04139509, -0.03704251, -0.00900633, -0.00396133, -0.05737834, -0.02138327, -0.02348181, -0.05697741, -0.02090438, + -0.01738146, +0.18423966, +0.00076020, -0.00963729, -0.05000374, +0.06060186, +0.04965385, +0.01803448, -0.02766864, +0.01075265, +0.03478151, +0.05366977, -0.00503948, -0.01800631, +0.00269439, -0.01353178, -0.00322737, +0.00472558, +0.03373770, +0.02488377, -0.01171508, -0.01104598, -0.01369414, + -0.01485625, -0.04750558, +0.00251646, -0.00778982, -0.03352974, +0.06884639, +0.05261376, +0.05168523, -0.02295379, +0.06161253, +0.03729243, +0.05610805, -0.00161580, -0.01443056, +0.00589340, -0.01001979, +0.00320386, +0.00516393, +0.03925103, +0.04004911, -0.00649968, -0.00295777, +0.00084709, + -0.01814584, -0.06311201, +0.00134572, -0.01370785, -0.03660314, +0.00194946, +0.13351371, +0.00237445, -0.05780018, -0.00628174, +0.02216614, +0.04820517, -0.00441034, -0.02095132, -0.02756035, -0.01796667, -0.00009157, +0.00477318, +0.17466768, +0.15000280, -0.01517861, -0.00550850, -0.00492212, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + -0.02154919, +0.00692654, +0.04980913, -0.00251802, -0.01868417, +0.01352013, +0.02158476, +0.00540484, +0.07986272, +0.00581852, -0.00192012, -0.00624639, +0.56747178, +0.00093316, -0.11703169, -0.13996237, -0.06495071, -0.06371575, +0.00562917, +0.00190997, -0.22378695, -0.34458297, +0.05750313, + +0.00984234, +0.02944556, -0.04819330, +0.02582492, +0.03120244, +0.02227068, +0.02371916, +0.01480154, +0.10434798, +0.01628340, +0.00901783, +0.00353080, +0.01006007, +0.02760006, -0.11217453, +0.02747884, -0.00782538, -0.01965921, +0.01544275, +0.00902907, +0.09449836, +0.02007733, -0.03257404, + -0.03469603, -0.08850647, -0.05019638, +0.01798319, +0.02791082, +0.02310299, +0.01550350, +0.02609716, +0.04852524, +0.03488700, +0.00507564, +0.00397832, +0.00430404, +0.15097843, -0.04419963, +0.01669760, -0.00668225, -0.02588015, +0.01493199, +0.00979906, +0.08813528, +0.00112152, -0.02963594, + +0.16584551, -0.04549649, -0.00768800, -0.01960165, -0.05094256, -0.06131821, -0.04738302, +0.06969377, -0.15308499, +0.08658396, -0.09689694, +0.13147061, -0.02045042, -0.03715100, +0.27670832, -0.05557155, -0.00653260, -0.00347530, +0.10469943, -0.08244843, -0.11900308, -0.03470326, -0.01482679, + +0.00067755, +0.00289983, +0.00271893, +0.00518988, +0.00176061, +0.00356567, +0.00275531, +0.00067785, -0.00047409, +0.00052159, +0.00026689, +0.00024586, +0.00159942, +0.00094933, +0.05012270, +0.00345823, +0.00717990, +0.00336474, +0.00124987, +0.00113262, -0.02705171, +0.00161459, +0.00319080, + -0.01047392, +0.00191471, +0.04798495, +0.01305862, +0.00029350, +0.00952184, +0.00681579, -0.00828447, +0.06131028, -0.00885080, -0.00211207, -0.01024898, -0.00744412, +0.00467417, -0.08310759, +0.00601258, -0.07349612, -0.07096262, -0.00396082, -0.00804289, +0.04375068, -0.00086971, +0.04574956, + -0.00418779, -0.00552606, -0.05703970, -0.00445312, -0.00809798, -0.00059174, -0.01211830, -0.00389659, +0.05281329, -0.00457078, -0.00262860, -0.00084249, -0.00054670, -0.01286794, +0.01640869, -0.00412427, +0.08257384, +0.06933862, -0.00306556, -0.00173914, -0.07003821, -0.00963086, -0.05281827, + +0.00067755, +0.00289983, +0.00271893, +0.00518988, +0.00176061, +0.00356567, +0.00275531, +0.00067785, -0.00047409, +0.00052159, +0.00026689, +0.00024586, +0.00159942, +0.00094933, +0.05012270, +0.00345823, +0.00717990, +0.00336474, +0.00124987, +0.00113262, -0.02705171, +0.00161459, +0.00319080, + -0.01439077, -0.00789314, -0.00982402, +0.00032744, -0.00937702, -0.00631269, +0.00088564, -0.01537552, -0.10072697, -0.01627608, -0.00518503, -0.01230494, -0.01025979, -0.00637964, +0.11246540, -0.00904550, +0.02958793, +0.01060124, -0.01090998, -0.01150913, -0.03442616, -0.01465652, -0.00964445, + +0.00067755, +0.00289983, +0.00271893, +0.00518988, +0.00176061, +0.00356567, +0.00275531, +0.00067785, -0.00047409, +0.00052159, +0.00026689, +0.00024586, +0.00159942, +0.00094933, +0.05012270, +0.00345823, +0.00717990, +0.00336474, +0.00124987, +0.00113262, -0.02705171, +0.00161459, +0.00319080, + +0.00067755, +0.00289983, +0.00271893, +0.00518988, +0.00176061, +0.00356567, +0.00275531, +0.00067785, -0.00047409, +0.00052159, +0.00026689, +0.00024586, +0.00159942, +0.00094933, +0.05012270, +0.00345823, +0.00717990, +0.00336474, +0.00124987, +0.00113262, -0.02705171, +0.00161459, +0.00319080, + +0.00067755, +0.00289983, +0.00271893, +0.00518988, +0.00176061, +0.00356567, +0.00275531, +0.00067785, -0.00047409, +0.00052159, +0.00026689, +0.00024586, +0.00159942, +0.00094933, +0.05012270, +0.00345823, +0.00717990, +0.00336474, +0.00124987, +0.00113262, -0.02705171, +0.00161459, +0.00319080, + +0.00067755, +0.00289983, +0.00271893, +0.00518988, +0.00176061, +0.00356567, +0.00275531, +0.00067785, -0.00047409, +0.00052159, +0.00026689, +0.00024586, +0.00159942, +0.00094933, +0.05012270, +0.00345823, +0.00717990, +0.00336474, +0.00124987, +0.00113262, -0.02705171, +0.00161459, +0.00319080, + +0.00067755, +0.00289983, +0.00271893, +0.00518988, +0.00176061, +0.00356567, +0.00275531, +0.00067785, -0.00047409, +0.00052159, +0.00026689, +0.00024586, +0.00159942, +0.00094933, +0.05012270, +0.00345823, +0.00717990, +0.00336474, +0.00124987, +0.00113262, -0.02705171, +0.00161459, +0.00319080, + +0.00067755, +0.00289983, +0.00271893, +0.00518988, +0.00176061, +0.00356567, +0.00275531, +0.00067785, -0.00047409, +0.00052159, +0.00026689, +0.00024586, +0.00159942, +0.00094933, +0.05012270, +0.00345823, +0.00717990, +0.00336474, +0.00124987, +0.00113262, -0.02705171, +0.00161459, +0.00319080, + +0.00067755, +0.00289983, +0.00271893, +0.00518988, +0.00176061, +0.00356567, +0.00275531, +0.00067785, -0.00047409, +0.00052159, +0.00026689, +0.00024586, +0.00159942, +0.00094933, +0.05012270, +0.00345823, +0.00717990, +0.00336474, +0.00124987, +0.00113262, -0.02705171, +0.00161459, +0.00319080, + -0.00541915, +0.01023137, +0.06067838, +0.16114352, -0.00447420, +0.00077779, +0.01710654, +0.00479846, -0.05621853, +0.00524657, +0.00212102, -0.00064071, -0.00661233, +0.01190237, +0.08207012, -0.00201205, -0.06855116, -0.06444122, +0.00498664, +0.00168039, -0.00404406, -0.01212722, +0.05853067, + -0.00293413, +0.02486269, -0.05144868, +0.16411800, +0.01292461, +0.00168762, +0.01781029, +0.01103859, -0.03745306, +0.01295915, +0.00751621, +0.00027908, -0.00200157, +0.02363901, +0.08422194, +0.00519868, -0.01247183, -0.02305624, +0.01057885, +0.00505845, -0.00265174, -0.00784309, -0.03685614, + +0.05848568, -0.01596364, -0.09439094, -0.09853172, -0.10236218, +0.12094092, -0.02037639, -0.01768102, -0.04205291, -0.01727278, -0.01954781, -0.04146721, +0.04042224, +0.07456448, +0.15279176, +0.06681152, -0.02519797, -0.04438342, -0.03095484, -0.04625892, +0.05799049, +0.09756843, -0.06443802, + -0.06154326, +0.02127358, -0.01808941, -0.02901769, +0.13076448, +0.02360887, +0.01032297, +0.12459198, -0.03738755, +0.15585680, +0.08412144, +0.09885526, -0.02666589, -0.03874216, +0.04139509, -0.03704251, -0.00900633, -0.00396133, -0.05737834, -0.02138327, -0.02348181, -0.05697741, -0.02090438, + -0.04572165, +0.02544448, -0.01315860, -0.01843593, -0.08675072, +0.02436687, +0.01074077, +0.12644257, -0.03617066, +0.15777243, +0.08740582, +0.10667121, -0.01507835, -0.03461225, +0.04212559, -0.02948520, -0.00850194, -0.00253437, -0.05671206, -0.01997501, -0.01711526, -0.02120804, -0.01918717, + -0.02386113, +0.16037460, -0.00937201, -0.02595734, -0.06907989, +0.14476735, +0.11621074, -0.05213094, -0.06401626, -0.08131084, +0.15651038, -0.05487272, -0.01341425, -0.03321461, -0.05190191, -0.03052012, -0.00902753, +0.00025191, +0.14000811, +0.09432571, -0.03420039, -0.02313457, -0.02213519, + -0.02067105, +0.16863323, -0.00041054, -0.01555532, -0.05307715, -0.00629507, +0.13055381, -0.03127631, -0.06251503, -0.05714162, +0.01965521, +0.04576688, -0.00783402, -0.02452707, -0.03075936, -0.02147865, -0.00652280, +0.00433483, +0.16915435, +0.13483746, -0.02039400, -0.01359671, -0.01946335, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.00582614, +0.01621089, +0.10972639, -0.11647793, +0.02698855, -0.14007133, +0.02905989, +0.00485424, +0.01152607, +0.00663521, +0.00677649, -0.00630848, +0.00662323, +0.02301023, -0.03023850, +0.02872512, -0.14677110, -0.13485506, +0.01895369, +0.02944251, +0.11883257, +0.03984136, +0.10330189, + -0.00293413, +0.02486269, -0.05144868, +0.16411800, +0.01292461, +0.00168762, +0.01781029, +0.01103859, -0.03745306, +0.01295915, +0.00751621, +0.00027908, -0.00200157, +0.02363901, +0.08422194, +0.00519868, -0.01247183, -0.02305624, +0.01057885, +0.00505845, -0.00265174, -0.00784309, -0.03685614, + +0.05848568, -0.01596364, -0.09439094, -0.09853172, -0.10236218, +0.12094092, -0.02037639, -0.01768102, -0.04205291, -0.01727278, -0.01954781, -0.04146721, +0.04042224, +0.07456448, +0.15279176, +0.06681152, -0.02519797, -0.04438342, -0.03095484, -0.04625892, +0.05799049, +0.09756843, -0.06443802, + -0.06154326, +0.02127358, -0.01808941, -0.02901769, +0.13076448, +0.02360887, +0.01032297, +0.12459198, -0.03738755, +0.15585680, +0.08412144, +0.09885526, -0.02666589, -0.03874216, +0.04139509, -0.03704251, -0.00900633, -0.00396133, -0.05737834, -0.02138327, -0.02348181, -0.05697741, -0.02090438, + -0.04572165, +0.02544448, -0.01315860, -0.01843593, -0.08675072, +0.02436687, +0.01074077, +0.12644257, -0.03617066, +0.15777243, +0.08740582, +0.10667121, -0.01507835, -0.03461225, +0.04212559, -0.02948520, -0.00850194, -0.00253437, -0.05671206, -0.01997501, -0.01711526, -0.02120804, -0.01918717, + -0.01611886, +0.06836704, +0.00163833, -0.00871355, -0.04176674, +0.06472412, +0.05113380, +0.03485985, -0.02531122, +0.03618259, +0.03603697, +0.05488891, -0.00332764, -0.01621844, +0.00429390, -0.01177578, -0.00001175, +0.00494475, +0.03649436, +0.03246644, -0.00910738, -0.00700188, -0.00642352, + -0.02067105, +0.16863323, -0.00041054, -0.01555532, -0.05307715, -0.00629507, +0.13055381, -0.03127631, -0.06251503, -0.05714162, +0.01965521, +0.04576688, -0.00783402, -0.02452707, -0.03075936, -0.02147865, -0.00652280, +0.00433483, +0.16915435, +0.13483746, -0.02039400, -0.01359671, -0.01946335, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + -0.02154919, +0.00692654, +0.04980913, -0.00251802, -0.01868417, +0.01352013, +0.02158476, +0.00540484, +0.07986272, +0.00581852, -0.00192012, -0.00624639, +0.56747178, +0.00093316, -0.11703169, -0.13996237, -0.06495071, -0.06371575, +0.00562917, +0.00190997, -0.22378695, -0.34458297, +0.05750313, + +0.00984234, +0.02944556, -0.04819330, +0.02582492, +0.03120244, +0.02227068, +0.02371916, +0.01480154, +0.10434798, +0.01628340, +0.00901783, +0.00353080, +0.01006007, +0.02760006, -0.11217453, +0.02747884, -0.00782538, -0.01965921, +0.01544275, +0.00902907, +0.09449836, +0.02007733, -0.03257404, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.16451352, -0.05289310, -0.01376501, -0.02882971, -0.05403575, -0.06761200, -0.05521109, +0.06825307, +0.06212907, +0.08546922, -0.09733928, +0.13090238, -0.02434002, -0.03863623, +0.11231508, -0.06475020, -0.02054697, -0.01012042, +0.10218928, -0.08431031, -0.17624752, -0.03737194, -0.02225051, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + -0.01528668, -0.00495934, +0.04394944, -0.00166792, -0.00493408, -0.00618102, -0.01134851, -0.01269318, -0.02323282, -0.01267800, -0.00310231, -0.01179927, -0.01210912, -0.00133712, -0.04042671, -0.00590688, -0.08317877, -0.07506884, -0.01020182, -0.01182201, +0.04467306, -0.00518497, +0.03896603, + -0.00250888, -0.00778021, -0.05945176, -0.00704065, -0.00884110, -0.00305924, -0.00588574, -0.00410500, -0.00076526, -0.00471276, -0.00272716, -0.00095050, -0.00146849, -0.01024079, -0.02497383, -0.00639215, +0.07591474, +0.06611660, -0.00333065, -0.00224118, -0.00249786, -0.01104749, -0.05517682, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + -0.01810234, -0.01433848, -0.01556876, -0.01265466, -0.01391571, -0.01454221, -0.01361285, -0.01720067, -0.04572617, -0.01769885, -0.00588713, -0.01293452, -0.01413625, -0.01185478, +0.00347981, -0.01715230, +0.01470732, +0.00372905, -0.01439450, -0.01440496, -0.02081138, -0.01808364, -0.01685830, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + -0.10869401, -0.03290697, -0.03846352, +0.05595634, +0.11454890, +0.12520934, -0.01717290, -0.01936626, -0.14484938, -0.02009159, -0.02382364, -0.03334610, +0.11822438, -0.04995670, -0.06009310, -0.97849923, -0.00683816, -0.01489578, -0.03157759, -0.04689658, +0.61564409, +0.46716315, -0.01730715, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, +0.00000000, + +0.00322211, +0.01084002, +0.06261719, +0.01331376, +0.01033666, +0.00922367, +0.00760642, +0.00483056, +0.00056532, +0.00526521, +0.00289928, +0.00130657, +0.00238372, +0.01080146, -0.02152276, +0.01180689, -0.06640745, -0.06178568, +0.00485940, +0.00300451, +0.06697671, +0.01309253, +0.05922004, + +0.00570714, +0.02547134, -0.04950988, +0.01628825, +0.02773547, +0.01013350, +0.00831017, +0.01107069, +0.01933079, +0.01297779, +0.00829448, +0.00222636, +0.00699449, +0.02253810, -0.01937094, +0.01901761, -0.01032812, -0.02040070, +0.01045161, +0.00638257, +0.06836903, +0.01737666, -0.03616678, + +0.11958637, -0.03534567, -0.07225901, -0.02803817, -0.05335357, +0.09536022, -0.07820679, +0.05319549, +0.07563117, +0.06762428, +0.04261650, +0.03193573, -0.03015602, +0.09378901, +0.08294021, -0.06308691, -0.02646583, -0.03685595, +0.08077119, -0.12511941, -0.10666545, -0.05068597, -0.06221067, + +0.04368939, +0.04943055, -0.11273331, +0.03789356, +0.05442610, -0.13046469, +0.03884093, +0.04963533, -0.10088367, +0.07076297, +0.02646441, -0.00180849, +0.01215596, -0.08098341, -0.01152281, +0.04742342, -0.03148111, -0.04697434, -0.16249394, +0.07488477, +0.20915607, +0.04528129, -0.08185856, + -0.17127311, -0.14796872, -0.10485143, +0.04232216, +0.10885701, +0.05546870, +0.04675907, -0.06074186, -0.16494225, -0.07196729, +0.10485102, -0.14218457, +0.02716308, +0.07264988, -0.05876779, +0.08151949, -0.02106803, -0.04797667, +0.09941927, +0.06005203, +0.26246217, +0.06020024, -0.06055994, + -0.04347579, -0.10189545, -0.05255458, -0.00202520, +0.02203623, +0.15053029, -0.02724176, -0.01668341, +0.01567925, -0.02399262, -0.00625465, -0.00322579, -0.00206878, +0.13849669, +0.01003917, -0.00150450, -0.01282899, -0.02721272, +0.18213091, -0.06267374, +0.00834977, -0.00666544, -0.03764053, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.00322211, +0.01084002, +0.06261719, +0.01331376, +0.01033666, +0.00922367, +0.00760642, +0.00483056, +0.00056532, +0.00526521, +0.00289928, +0.00130657, +0.00238372, +0.01080146, -0.02152276, +0.01180689, -0.06640745, -0.06178568, +0.00485940, +0.00300451, +0.06697671, +0.01309253, +0.05922004, + +0.00570714, +0.02547134, -0.04950988, +0.01628825, +0.02773547, +0.01013350, +0.00831017, +0.01107069, +0.01933079, +0.01297779, +0.00829448, +0.00222636, +0.00699449, +0.02253810, -0.01937094, +0.01901761, -0.01032812, -0.02040070, +0.01045161, +0.00638257, +0.06836903, +0.01737666, -0.03616678, + +0.11958637, -0.03534567, -0.07225901, -0.02803817, -0.05335357, +0.09536022, -0.07820679, +0.05319549, +0.07563117, +0.06762428, +0.04261650, +0.03193573, -0.03015602, +0.09378901, +0.08294021, -0.06308691, -0.02646583, -0.03685595, +0.08077119, -0.12511941, -0.10666545, -0.05068597, -0.06221067, + +0.04368939, +0.04943055, -0.11273331, +0.03789356, +0.05442610, -0.13046469, +0.03884093, +0.04963533, -0.10088367, +0.07076297, +0.02646441, -0.00180849, +0.01215596, -0.08098341, -0.01152281, +0.04742342, -0.03148111, -0.04697434, -0.16249394, +0.07488477, +0.20915607, +0.04528129, -0.08185856, + +0.00730811, -0.08760823, -0.04760039, +0.01827355, +0.03626214, +0.01520328, +0.01393376, +0.02833428, -0.10006786, +0.03875799, +0.00962240, +0.00361883, +0.01059105, +0.02457565, +0.05616220, +0.02559745, -0.00688253, -0.02010249, +0.01379498, +0.01427240, +0.10307143, +0.02214003, -0.02691152, + -0.11777180, -0.13019881, -0.09111938, +0.06589182, +0.13834257, -0.07022484, +0.09542955, -0.00297998, -0.28023424, +0.00492628, -0.02107881, -0.03557755, +0.04383975, -0.03423818, -0.00889070, +0.11558565, -0.01439868, -0.03703290, -0.05779085, +0.14522027, +0.35887369, +0.09406519, -0.04803316, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + -0.02568439, +0.00295232, +0.04849255, -0.01205469, -0.02215115, +0.00138295, +0.00617576, +0.00167399, -0.00515447, +0.00251291, -0.00264348, -0.00755082, +0.56440620, -0.00412880, -0.02422811, -0.14842360, -0.06745346, -0.06445723, +0.00063803, -0.00073653, -0.24991628, -0.34728364, +0.05391039, + +0.00570714, +0.02547134, -0.04950988, +0.01628825, +0.02773547, +0.01013350, +0.00831017, +0.01107069, +0.01933079, +0.01297779, +0.00829448, +0.00222636, +0.00699449, +0.02253810, -0.01937094, +0.01901761, -0.01032812, -0.02040070, +0.01045161, +0.00638257, +0.06836903, +0.01737666, -0.03616678, + -0.04118770, -0.09312636, -0.05181984, +0.00584417, +0.02342636, +0.00986764, -0.00889336, +0.02189687, +0.01756068, +0.03120178, +0.00418396, +0.00253603, +0.00056083, +0.14233999, +0.03986376, +0.00704601, -0.00970580, -0.02676435, +0.00895607, +0.00652199, +0.02151731, -0.00177710, -0.03406092, + -0.03051243, -0.01223842, +0.06192271, -0.00295116, -0.03499272, -0.00009132, +0.00927222, -0.01058823, -0.02518193, -0.01502829, +0.13467536, -0.08918981, -0.00326077, +0.12965824, +0.00929954, -0.01741536, +0.06530373, +0.04470146, -0.00732600, -0.00464145, -0.00334399, -0.02500172, +0.05667624, + -0.03051243, -0.01223842, +0.06192271, -0.00295116, -0.03499272, -0.00009132, +0.00927222, -0.01058823, -0.02518193, -0.01502829, +0.13467536, -0.08918981, -0.00326077, +0.12965824, +0.00929954, -0.01741536, +0.06530373, +0.04470146, -0.00732600, -0.00464145, -0.00334399, -0.02500172, +0.05667624, + -0.03051243, -0.01223842, +0.06192271, -0.00295116, -0.03499272, -0.00009132, +0.00927222, -0.01058823, -0.02518193, -0.01502829, +0.13467536, -0.08918981, -0.00326077, +0.12965824, +0.00929954, -0.01741536, +0.06530373, +0.04470146, -0.00732600, -0.00464145, -0.00334399, -0.02500172, +0.05667624, + -0.03051243, -0.01223842, +0.06192271, -0.00295116, -0.03499272, -0.00009132, +0.00927222, -0.01058823, -0.02518193, -0.01502829, +0.13467536, -0.08918981, -0.00326077, +0.12965824, +0.00929954, -0.01741536, +0.06530373, +0.04470146, -0.00732600, -0.00464145, -0.00334399, -0.02500172, +0.05667624, + -0.03051243, -0.01223842, +0.06192271, -0.00295116, -0.03499272, -0.00009132, +0.00927222, -0.01058823, -0.02518193, -0.01502829, +0.13467536, -0.08918981, -0.00326077, +0.12965824, +0.00929954, -0.01741536, +0.06530373, +0.04470146, -0.00732600, -0.00464145, -0.00334399, -0.02500172, +0.05667624, + -0.03051243, -0.01223842, +0.06192271, -0.00295116, -0.03499272, -0.00009132, +0.00927222, -0.01058823, -0.02518193, -0.01502829, +0.13467536, -0.08918981, -0.00326077, +0.12965824, +0.00929954, -0.01741536, +0.06530373, +0.04470146, -0.00732600, -0.00464145, -0.00334399, -0.02500172, +0.05667624, + -0.03051243, -0.01223842, +0.06192271, -0.00295116, -0.03499272, -0.00009132, +0.00927222, -0.01058823, -0.02518193, -0.01502829, +0.13467536, -0.08918981, -0.00326077, +0.12965824, +0.00929954, -0.01741536, +0.06530373, +0.04470146, -0.00732600, -0.00464145, -0.00334399, -0.02500172, +0.05667624, + -0.03051243, -0.01223842, +0.06192271, -0.00295116, -0.03499272, -0.00009132, +0.00927222, -0.01058823, -0.02518193, -0.01502829, +0.13467536, -0.08918981, -0.00326077, +0.12965824, +0.00929954, -0.01741536, +0.06530373, +0.04470146, -0.00732600, -0.00464145, -0.00334399, -0.02500172, +0.05667624, + -0.03051243, -0.01223842, +0.06192271, -0.00295116, -0.03499272, -0.00009132, +0.00927222, -0.01058823, -0.02518193, -0.01502829, +0.13467536, -0.08918981, -0.00326077, +0.12965824, +0.00929954, -0.01741536, +0.06530373, +0.04470146, -0.00732600, -0.00464145, -0.00334399, -0.02500172, +0.05667624, + -0.03051243, -0.01223842, +0.06192271, -0.00295116, -0.03499272, -0.00009132, +0.00927222, -0.01058823, -0.02518193, -0.01502829, +0.13467536, -0.08918981, -0.00326077, +0.12965824, +0.00929954, -0.01741536, +0.06530373, +0.04470146, -0.00732600, -0.00464145, -0.00334399, -0.02500172, +0.05667624, + -0.03051243, -0.01223842, +0.06192271, -0.00295116, -0.03499272, -0.00009132, +0.00927222, -0.01058823, -0.02518193, -0.01502829, +0.13467536, -0.08918981, -0.00326077, +0.12965824, +0.00929954, -0.01741536, +0.06530373, +0.04470146, -0.00732600, -0.00464145, -0.00334399, -0.02500172, +0.05667624, + -0.03051243, -0.01223842, +0.06192271, -0.00295116, -0.03499272, -0.00009132, +0.00927222, -0.01058823, -0.02518193, -0.01502829, +0.13467536, -0.08918981, -0.00326077, +0.12965824, +0.00929954, -0.01741536, +0.06530373, +0.04470146, -0.00732600, -0.00464145, -0.00334399, -0.02500172, +0.05667624, + -0.03051243, -0.01223842, +0.06192271, -0.00295116, -0.03499272, -0.00009132, +0.00927222, -0.01058823, -0.02518193, -0.01502829, +0.13467536, -0.08918981, -0.00326077, +0.12965824, +0.00929954, -0.01741536, +0.06530373, +0.04470146, -0.00732600, -0.00464145, -0.00334399, -0.02500172, +0.05667624, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.20000891, -0.03366086, +0.10323489, +0.03228159, +0.00237928, -0.03601483, -0.00217185, -0.07707866, -0.03169604, -0.10721804, -0.03046394, +0.27321343, +0.00752145, +0.03747129, -0.01864830, +0.00458223, -0.13957099, +0.15531746, -0.03663309, -0.02442578, -0.01946787, +0.01449404, -0.08546495, + +0.02433807, -0.02887462, +0.11021833, +0.04506234, +0.04259051, -0.03283402, +0.00129829, -0.04554216, -0.02921180, -0.06104863, +0.04330810, +0.07423422, +0.02298455, +0.06291205, -0.00910151, +0.04447715, -0.13894494, +0.15978721, -0.02651686, -0.01978197, -0.01128624, +0.04321650, -0.08389430, + +0.07324800, -0.06780101, +0.25415601, +0.08530311, +0.08448060, -0.07740996, -0.01514361, -0.10217161, -0.06683703, -0.13237189, +0.08751529, +0.13680983, +0.04010291, -0.02578116, -0.03488197, +0.09081438, -0.14907850, +0.09908995, -0.06390468, -0.04766818, -0.02275646, +0.09698198, -0.17108476, + -0.01874257, -0.03462222, +0.05783124, +0.03490223, +0.02802017, -0.03649679, +0.00008356, -0.05197860, -0.04459652, -0.06871720, +0.03640743, +0.07278698, +0.01435791, +0.20237873, -0.01132652, +0.02490331, -0.28452765, +0.36698853, -0.03070711, -0.02650426, -0.03340592, +0.01439003, -0.10085213, + +0.02433807, -0.02887462, +0.11021833, +0.04506234, +0.04259051, -0.03283402, +0.00129829, -0.04554216, -0.02921180, -0.06104863, +0.04330810, +0.07423422, +0.02298455, +0.06291205, -0.00910151, +0.04447715, -0.13894494, +0.15978721, -0.02651686, -0.01978197, -0.01128624, +0.04321650, -0.08389430, + +0.02433807, -0.02887462, +0.11021833, +0.04506234, +0.04259051, -0.03283402, +0.00129829, -0.04554216, -0.02921180, -0.06104863, +0.04330810, +0.07423422, +0.02298455, +0.06291205, -0.00910151, +0.04447715, -0.13894494, +0.15978721, -0.02651686, -0.01978197, -0.01128624, +0.04321650, -0.08389430, + +0.02433807, -0.02887462, +0.11021833, +0.04506234, +0.04259051, -0.03283402, +0.00129829, -0.04554216, -0.02921180, -0.06104863, +0.04330810, +0.07423422, +0.02298455, +0.06291205, -0.00910151, +0.04447715, -0.13894494, +0.15978721, -0.02651686, -0.01978197, -0.01128624, +0.04321650, -0.08389430, + +0.02433807, -0.02887462, +0.11021833, +0.04506234, +0.04259051, -0.03283402, +0.00129829, -0.04554216, -0.02921180, -0.06104863, +0.04330810, +0.07423422, +0.02298455, +0.06291205, -0.00910151, +0.04447715, -0.13894494, +0.15978721, -0.02651686, -0.01978197, -0.01128624, +0.04321650, -0.08389430, + +0.02433807, -0.02887462, +0.11021833, +0.04506234, +0.04259051, -0.03283402, +0.00129829, -0.04554216, -0.02921180, -0.06104863, +0.04330810, +0.07423422, +0.02298455, +0.06291205, -0.00910151, +0.04447715, -0.13894494, +0.15978721, -0.02651686, -0.01978197, -0.01128624, +0.04321650, -0.08389430, + +0.02433807, -0.02887462, +0.11021833, +0.04506234, +0.04259051, -0.03283402, +0.00129829, -0.04554216, -0.02921180, -0.06104863, +0.04330810, +0.07423422, +0.02298455, +0.06291205, -0.00910151, +0.04447715, -0.13894494, +0.15978721, -0.02651686, -0.01978197, -0.01128624, +0.04321650, -0.08389430, + +0.02433807, -0.02887462, +0.11021833, +0.04506234, +0.04259051, -0.03283402, +0.00129829, -0.04554216, -0.02921180, -0.06104863, +0.04330810, +0.07423422, +0.02298455, +0.06291205, -0.00910151, +0.04447715, -0.13894494, +0.15978721, -0.02651686, -0.01978197, -0.01128624, +0.04321650, -0.08389430, + +0.02433807, -0.02887462, +0.11021833, +0.04506234, +0.04259051, -0.03283402, +0.00129829, -0.04554216, -0.02921180, -0.06104863, +0.04330810, +0.07423422, +0.02298455, +0.06291205, -0.00910151, +0.04447715, -0.13894494, +0.15978721, -0.02651686, -0.01978197, -0.01128624, +0.04321650, -0.08389430, + +0.02433807, -0.02887462, +0.11021833, +0.04506234, +0.04259051, -0.03283402, +0.00129829, -0.04554216, -0.02921180, -0.06104863, +0.04330810, +0.07423422, +0.02298455, +0.06291205, -0.00910151, +0.04447715, -0.13894494, +0.15978721, -0.02651686, -0.01978197, -0.01128624, +0.04321650, -0.08389430, + +0.05645667, -0.02422138, +0.16080624, +0.20153310, +0.04106746, -0.03611656, +0.00199065, -0.03955955, -0.01628415, -0.05374743, +0.04916742, +0.07370652, +0.02125334, -0.07941886, -0.00864310, +0.05099822, +0.00630063, -0.04924618, -0.02290526, -0.01538368, -0.00914543, +0.04705573, -0.06760565, + +0.05785313, -0.02169968, -0.04116444, +0.20316428, +0.04958388, -0.03587780, +0.00224659, -0.03881937, -0.01084026, -0.05311859, +0.05224425, +0.07436968, +0.02345970, -0.07563261, -0.00804061, +0.05619518, +0.01036473, -0.01337385, -0.02151895, -0.01476580, -0.00856961, +0.04851122, +0.00007445, + -0.02704822, -0.04347584, -0.07490696, -0.02095164, -0.02986715, -0.05275208, -0.00151170, -0.04766970, -0.03395120, -0.06085026, +0.03686052, +0.05015746, +0.09456764, -0.11820748, -0.01565406, +0.18825136, +0.00682287, -0.02480436, -0.03445483, -0.02311196, +0.03673172, +0.22325800, -0.01301188, + +0.24867674, -0.02625102, -0.04667659, +0.03668763, +0.26304512, -0.03017960, +0.00199771, -0.04174816, -0.01162738, -0.05621227, +0.04922257, +0.05437012, +0.01068406, -0.10035223, -0.00773161, +0.02910671, +0.00990294, -0.01439925, -0.02298644, -0.01465906, -0.00236842, +0.01390107, -0.00170683, + +0.26449836, -0.02208011, -0.04174578, +0.04726940, +0.04552993, -0.02942160, +0.00241550, -0.03989757, -0.01041048, -0.05429664, +0.05250696, +0.06218607, +0.02227161, -0.09622232, -0.00700111, +0.03666403, +0.01040733, -0.01297228, -0.02232016, -0.01325080, +0.00399814, +0.04967045, +0.00001038, + -0.04277233, -0.00195982, -0.01302461, -0.00853495, +0.16213887, -0.01000367, -0.00268614, -0.06982418, +0.02075711, -0.10150631, +0.14034418, +0.23204062, -0.01296270, -0.01003093, -0.00697407, -0.01839396, +0.01415810, -0.00188938, -0.02532942, -0.01069554, +0.01101634, -0.03739972, +0.01326647, + -0.00422096, +0.00900522, +0.00528697, +0.00851425, -0.02005279, +0.00307950, +0.00834330, -0.02522493, +0.02288607, -0.04082373, +0.07481508, +0.12648120, +0.00655884, +0.00311877, +0.00633019, +0.00343856, +0.01571690, +0.00641037, -0.00480096, +0.00276962, +0.01984327, +0.00832358, +0.01761885, + -0.00693837, +0.00552253, -0.00349088, +0.00524333, -0.03531244, -0.00655397, +0.00084833, -0.03796913, +0.02243095, -0.05496669, +0.21662196, +0.02671881, +0.00254200, -0.00391420, +0.00257613, -0.00352565, +0.01499401, +0.00257683, -0.01592678, -0.00545248, +0.01815341, +0.00326410, +0.01582107, + -0.00693837, +0.00552253, -0.00349088, +0.00524333, -0.03531244, -0.00655397, +0.00084833, -0.03796913, +0.02243095, -0.05496669, +0.21662196, +0.02671881, +0.00254200, -0.00391420, +0.00257613, -0.00352565, +0.01499401, +0.00257683, -0.01592678, -0.00545248, +0.01815341, +0.00326410, +0.01582107, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.12729069, -0.06095906, +0.30834228, -0.05084743, +0.11514432, -0.06680188, -0.01340650, -0.09528133, -0.04899525, -0.12433594, +0.09545732, +0.14023200, +0.05908741, -0.16238362, -0.03089037, +0.12344099, -0.00315867, -0.10627929, -0.05913576, -0.03862189, +0.01934206, +0.15079570, -0.15345773, + +0.05785313, -0.02169968, -0.04116444, +0.20316428, +0.04958388, -0.03587780, +0.00224659, -0.03881937, -0.01084026, -0.05311859, +0.05224425, +0.07436968, +0.02345970, -0.07563261, -0.00804061, +0.05619518, +0.01036473, -0.01337385, -0.02151895, -0.01476580, -0.00856961, +0.04851122, +0.00007445, + -0.02704822, -0.04347584, -0.07490696, -0.02095164, -0.02986715, -0.05275208, -0.00151170, -0.04766970, -0.03395120, -0.06085026, +0.03686052, +0.05015746, +0.09456764, -0.11820748, -0.01565406, +0.18825136, +0.00682287, -0.02480436, -0.03445483, -0.02311196, +0.03673172, +0.22325800, -0.01301188, + +0.24867674, -0.02625102, -0.04667659, +0.03668763, +0.26304512, -0.03017960, +0.00199771, -0.04174816, -0.01162738, -0.05621227, +0.04922257, +0.05437012, +0.01068406, -0.10035223, -0.00773161, +0.02910671, +0.00990294, -0.01439925, -0.02298644, -0.01465906, -0.00236842, +0.01390107, -0.00170683, + +0.26449836, -0.02208011, -0.04174578, +0.04726940, +0.04552993, -0.02942160, +0.00241550, -0.03989757, -0.01041048, -0.05429664, +0.05250696, +0.06218607, +0.02227161, -0.09622232, -0.00700111, +0.03666403, +0.01040733, -0.01297228, -0.02232016, -0.01325080, +0.00399814, +0.04967045, +0.00001038, + -0.04277233, -0.00195982, -0.01302461, -0.00853495, +0.16213887, -0.01000367, -0.00268614, -0.06982418, +0.02075711, -0.10150631, +0.14034418, +0.23204062, -0.01296270, -0.01003093, -0.00697407, -0.01839396, +0.01415810, -0.00188938, -0.02532942, -0.01069554, +0.01101634, -0.03739972, +0.01326647, + -0.00422096, +0.00900522, +0.00528697, +0.00851425, -0.02005279, +0.00307950, +0.00834330, -0.02522493, +0.02288607, -0.04082373, +0.07481508, +0.12648120, +0.00655884, +0.00311877, +0.00633019, +0.00343856, +0.01571690, +0.00641037, -0.00480096, +0.00276962, +0.01984327, +0.00832358, +0.01761885, + -0.00422096, +0.00900522, +0.00528697, +0.00851425, -0.02005279, +0.00307950, +0.00834330, -0.02522493, +0.02288607, -0.04082373, +0.07481508, +0.12648120, +0.00655884, +0.00311877, +0.00633019, +0.00343856, +0.01571690, +0.00641037, -0.00480096, +0.00276962, +0.01984327, +0.00832358, +0.01761885, + -0.00422096, +0.00900522, +0.00528697, +0.00851425, -0.02005279, +0.00307950, +0.00834330, -0.02522493, +0.02288607, -0.04082373, +0.07481508, +0.12648120, +0.00655884, +0.00311877, +0.00633019, +0.00343856, +0.01571690, +0.00641037, -0.00480096, +0.00276962, +0.01984327, +0.00832358, +0.01761885, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.03851221, -0.03101472, +0.14848078, +0.02985400, +0.02467303, -0.03701197, +0.00108237, -0.04226229, -0.01954688, -0.05613235, +0.04466602, +0.06682406, +0.59363368, -0.09148490, -0.00958186, -0.09617949, +0.00559175, -0.05008566, -0.02654797, -0.01680072, -0.30605956, -0.28833319, -0.07224610, + +0.06881517, -0.02060533, -0.03936525, +0.05685363, +0.06567727, -0.02893249, +0.00276897, -0.03836554, -0.00838319, -0.05275122, +0.05328561, +0.07634462, +0.03381756, -0.07276839, -0.00627402, +0.06924795, +0.01070186, -0.01154177, -0.02094030, -0.01244180, +0.01140924, +0.07349847, +0.00074365, + +0.03333057, -0.03037219, -0.05383179, +0.02580618, +0.02274132, -0.03824786, +0.00108823, -0.04225889, -0.01501138, -0.05618564, +0.04664478, +0.06587107, +0.31238881, -0.09199917, -0.00963771, -0.17927328, +0.00916374, -0.01526599, -0.02578270, -0.01721698, -0.47181837, +0.36261582, -0.00539534, + +0.00817280, +0.00960566, +0.00491395, +0.01050476, +0.00515014, +0.01509031, -0.11244887, +0.00589050, -0.23529565, +0.00518800, +0.00477699, +0.00191498, +0.00491674, +0.02991267, +0.12747729, +0.00937796, +0.03275239, +0.01733398, +0.01946288, +0.06191324, +0.09919685, +0.00213021, +0.00793116, + +0.00817280, +0.00960566, +0.00491395, +0.01050476, +0.00515014, +0.01509031, -0.11244887, +0.00589050, -0.23529565, +0.00518800, +0.00477699, +0.00191498, +0.00491674, +0.02991267, +0.12747729, +0.00937796, +0.03275239, +0.01733398, +0.01946288, +0.06191324, +0.09919685, +0.00213021, +0.00793116, + +0.00817280, +0.00960566, +0.00491395, +0.01050476, +0.00515014, +0.01509031, -0.11244887, +0.00589050, -0.23529565, +0.00518800, +0.00477699, +0.00191498, +0.00491674, +0.02991267, +0.12747729, +0.00937796, +0.03275239, +0.01733398, +0.01946288, +0.06191324, +0.09919685, +0.00213021, +0.00793116, + +0.00817280, +0.00960566, +0.00491395, +0.01050476, +0.00515014, +0.01509031, -0.11244887, +0.00589050, -0.23529565, +0.00518800, +0.00477699, +0.00191498, +0.00491674, +0.02991267, +0.12747729, +0.00937796, +0.03275239, +0.01733398, +0.01946288, +0.06191324, +0.09919685, +0.00213021, +0.00793116, + +0.00817280, +0.00960566, +0.00491395, +0.01050476, +0.00515014, +0.01509031, -0.11244887, +0.00589050, -0.23529565, +0.00518800, +0.00477699, +0.00191498, +0.00491674, +0.02991267, +0.12747729, +0.00937796, +0.03275239, +0.01733398, +0.01946288, +0.06191324, +0.09919685, +0.00213021, +0.00793116, + +0.00817280, +0.00960566, +0.00491395, +0.01050476, +0.00515014, +0.01509031, -0.11244887, +0.00589050, -0.23529565, +0.00518800, +0.00477699, +0.00191498, +0.00491674, +0.02991267, +0.12747729, +0.00937796, +0.03275239, +0.01733398, +0.01946288, +0.06191324, +0.09919685, +0.00213021, +0.00793116, + +0.00817280, +0.00960566, +0.00491395, +0.01050476, +0.00515014, +0.01509031, -0.11244887, +0.00589050, -0.23529565, +0.00518800, +0.00477699, +0.00191498, +0.00491674, +0.02991267, +0.12747729, +0.00937796, +0.03275239, +0.01733398, +0.01946288, +0.06191324, +0.09919685, +0.00213021, +0.00793116, + +0.00817280, +0.00960566, +0.00491395, +0.01050476, +0.00515014, +0.01509031, -0.11244887, +0.00589050, -0.23529565, +0.00518800, +0.00477699, +0.00191498, +0.00491674, +0.02991267, +0.12747729, +0.00937796, +0.03275239, +0.01733398, +0.01946288, +0.06191324, +0.09919685, +0.00213021, +0.00793116, + +0.00817280, +0.00960566, +0.00491395, +0.01050476, +0.00515014, +0.01509031, -0.11244887, +0.00589050, -0.23529565, +0.00518800, +0.00477699, +0.00191498, +0.00491674, +0.02991267, +0.12747729, +0.00937796, +0.03275239, +0.01733398, +0.01946288, +0.06191324, +0.09919685, +0.00213021, +0.00793116, + +0.00817280, +0.00960566, +0.00491395, +0.01050476, +0.00515014, +0.01509031, -0.11244887, +0.00589050, -0.23529565, +0.00518800, +0.00477699, +0.00191498, +0.00491674, +0.02991267, +0.12747729, +0.00937796, +0.03275239, +0.01733398, +0.01946288, +0.06191324, +0.09919685, +0.00213021, +0.00793116, + +0.00817280, +0.00960566, +0.00491395, +0.01050476, +0.00515014, +0.01509031, -0.11244887, +0.00589050, -0.23529565, +0.00518800, +0.00477699, +0.00191498, +0.00491674, +0.02991267, +0.12747729, +0.00937796, +0.03275239, +0.01733398, +0.01946288, +0.06191324, +0.09919685, +0.00213021, +0.00793116, + +0.00817280, +0.00960566, +0.00491395, +0.01050476, +0.00515014, +0.01509031, -0.11244887, +0.00589050, -0.23529565, +0.00518800, +0.00477699, +0.00191498, +0.00491674, +0.02991267, +0.12747729, +0.00937796, +0.03275239, +0.01733398, +0.01946288, +0.06191324, +0.09919685, +0.00213021, +0.00793116, + +0.00817280, +0.00960566, +0.00491395, +0.01050476, +0.00515014, +0.01509031, -0.11244887, +0.00589050, -0.23529565, +0.00518800, +0.00477699, +0.00191498, +0.00491674, +0.02991267, +0.12747729, +0.00937796, +0.03275239, +0.01733398, +0.01946288, +0.06191324, +0.09919685, +0.00213021, +0.00793116, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01197859, +0.02111471, +0.00958824, +0.02766681, +0.01092412, +0.04305402, -0.07995758, +0.03657699, -0.06400526, +0.04847969, +0.00856970, +0.01002263, +0.01153141, +0.03400084, -0.10522660, +0.02669493, +0.04480594, +0.02237207, +0.03278491, +0.07091963, -0.03223210, +0.02047987, +0.01679363, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.02423895, +0.03516026, +0.01188503, -0.10799360, +0.02939837, -0.07453347, -0.02116598, +0.05994469, -0.05957423, +0.07791474, +0.01992533, +0.01457123, +0.02452164, +0.04195439, -0.08102380, +0.04273385, +0.04859973, +0.02457240, +0.09078679, -0.10080879, +0.00187557, +0.05170431, +0.02061345, + +0.02423895, +0.03516026, +0.01188503, -0.10799360, +0.02939837, -0.07453347, -0.02116598, +0.05994469, -0.05957423, +0.07791474, +0.01992533, +0.01457123, +0.02452164, +0.04195439, -0.08102380, +0.04273385, +0.04859973, +0.02457240, +0.09078679, -0.10080879, +0.00187557, +0.05170431, +0.02061345, + +0.02423895, +0.03516026, +0.01188503, -0.10799360, +0.02939837, -0.07453347, -0.02116598, +0.05994469, -0.05957423, +0.07791474, +0.01992533, +0.01457123, +0.02452164, +0.04195439, -0.08102380, +0.04273385, +0.04859973, +0.02457240, +0.09078679, -0.10080879, +0.00187557, +0.05170431, +0.02061345, + +0.02423895, +0.03516026, +0.01188503, -0.10799360, +0.02939837, -0.07453347, -0.02116598, +0.05994469, -0.05957423, +0.07791474, +0.01992533, +0.01457123, +0.02452164, +0.04195439, -0.08102380, +0.04273385, +0.04859973, +0.02457240, +0.09078679, -0.10080879, +0.00187557, +0.05170431, +0.02061345, + +0.02423895, +0.03516026, +0.01188503, -0.10799360, +0.02939837, -0.07453347, -0.02116598, +0.05994469, -0.05957423, +0.07791474, +0.01992533, +0.01457123, +0.02452164, +0.04195439, -0.08102380, +0.04273385, +0.04859973, +0.02457240, +0.09078679, -0.10080879, +0.00187557, +0.05170431, +0.02061345, + +0.02423895, +0.03516026, +0.01188503, -0.10799360, +0.02939837, -0.07453347, -0.02116598, +0.05994469, -0.05957423, +0.07791474, +0.01992533, +0.01457123, +0.02452164, +0.04195439, -0.08102380, +0.04273385, +0.04859973, +0.02457240, +0.09078679, -0.10080879, +0.00187557, +0.05170431, +0.02061345, + +0.02423895, +0.03516026, +0.01188503, -0.10799360, +0.02939837, -0.07453347, -0.02116598, +0.05994469, -0.05957423, +0.07791474, +0.01992533, +0.01457123, +0.02452164, +0.04195439, -0.08102380, +0.04273385, +0.04859973, +0.02457240, +0.09078679, -0.10080879, +0.00187557, +0.05170431, +0.02061345, + +0.02423895, +0.03516026, +0.01188503, -0.10799360, +0.02939837, -0.07453347, -0.02116598, +0.05994469, -0.05957423, +0.07791474, +0.01992533, +0.01457123, +0.02452164, +0.04195439, -0.08102380, +0.04273385, +0.04859973, +0.02457240, +0.09078679, -0.10080879, +0.00187557, +0.05170431, +0.02061345, + +0.02423895, +0.03516026, +0.01188503, -0.10799360, +0.02939837, -0.07453347, -0.02116598, +0.05994469, -0.05957423, +0.07791474, +0.01992533, +0.01457123, +0.02452164, +0.04195439, -0.08102380, +0.04273385, +0.04859973, +0.02457240, +0.09078679, -0.10080879, +0.00187557, +0.05170431, +0.02061345, + +0.02423895, +0.03516026, +0.01188503, -0.10799360, +0.02939837, -0.07453347, -0.02116598, +0.05994469, -0.05957423, +0.07791474, +0.01992533, +0.01457123, +0.02452164, +0.04195439, -0.08102380, +0.04273385, +0.04859973, +0.02457240, +0.09078679, -0.10080879, +0.00187557, +0.05170431, +0.02061345, + +0.02423895, +0.03516026, +0.01188503, -0.10799360, +0.02939837, -0.07453347, -0.02116598, +0.05994469, -0.05957423, +0.07791474, +0.01992533, +0.01457123, +0.02452164, +0.04195439, -0.08102380, +0.04273385, +0.04859973, +0.02457240, +0.09078679, -0.10080879, +0.00187557, +0.05170431, +0.02061345, + +0.02423895, +0.03516026, +0.01188503, -0.10799360, +0.02939837, -0.07453347, -0.02116598, +0.05994469, -0.05957423, +0.07791474, +0.01992533, +0.01457123, +0.02452164, +0.04195439, -0.08102380, +0.04273385, +0.04859973, +0.02457240, +0.09078679, -0.10080879, +0.00187557, +0.05170431, +0.02061345, + +0.02423895, +0.03516026, +0.01188503, -0.10799360, +0.02939837, -0.07453347, -0.02116598, +0.05994469, -0.05957423, +0.07791474, +0.01992533, +0.01457123, +0.02452164, +0.04195439, -0.08102380, +0.04273385, +0.04859973, +0.02457240, +0.09078679, -0.10080879, +0.00187557, +0.05170431, +0.02061345, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, + +0.01850879, +0.01579936, +0.01866775, +0.01498169, +0.01527074, +0.01540469, +0.01895493, +0.01752374, +0.02379814, +0.01794321, +0.00600160, +0.01310584, +0.01449284, +0.01213857, +0.01890395, +0.01771376, +0.01677132, +0.01328317, +0.01506122, +0.01482652, +0.02230365, +0.01827750, +0.02025401, +}; + +static int _labels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22}; + +struct model FPmodel = { + {0}, + 23, + 661, + _w, + _labels, + -1.00000000 +}; + +std::vector load_fp_matches() { + std::vector matches; + { + FingerMatch match; + match.line = -1; + match.OS_name = (char *) "FreeBSD 8.1-RELEASE"; + { + OS_Classification osclass = {"FreeBSD", "FreeBSD", "8.X", "general purpose"}; + match.OS_class.push_back(osclass); + } + matches.push_back(match); + } + { + FingerMatch match; + match.line = -1; + match.OS_name = (char *) "HP LaserJet M1212nf printer"; + { + OS_Classification osclass = {"HP", "embedded", NULL, "printer"}; + match.OS_class.push_back(osclass); + } + matches.push_back(match); + } + { + FingerMatch match; + match.line = -1; + match.OS_name = (char *) "Microsoft Windows XP SP3"; + { + OS_Classification osclass = {"Microsoft", "Windows", "XP", "general purpose"}; + match.OS_class.push_back(osclass); + } + matches.push_back(match); + } + { + FingerMatch match; + match.line = -1; + match.OS_name = (char *) "OpenIndiana oi_148"; + { + OS_Classification osclass = {"OpenIndiana", "OpenIndiana", NULL, "general purpose"}; + match.OS_class.push_back(osclass); + } + matches.push_back(match); + } + { + FingerMatch match; + match.line = -1; + match.OS_name = (char *) "Thecus N4100 NAS device (Linux 2.6.33)"; + { + OS_Classification osclass = {"Thecus", "Linux", "2.6.X", "storage-misc"}; + match.OS_class.push_back(osclass); + } + matches.push_back(match); + } + { + FingerMatch match; + match.line = -1; + match.OS_name = (char *) "Sun OpenSolaris snv_111b"; + { + OS_Classification osclass = {"OpenSolaris", "OpenSolaris", NULL, "general purpose"}; + match.OS_class.push_back(osclass); + } + matches.push_back(match); + } + { + FingerMatch match; + match.line = -1; + match.OS_name = (char *) "OpenBSD 4.4"; + { + OS_Classification osclass = {"OpenBSD", "OpenBSD", "4.X", "general purpose"}; + match.OS_class.push_back(osclass); + } + matches.push_back(match); + } + { + FingerMatch match; + match.line = -1; + match.OS_name = (char *) "Apple Mac OS X 10.4.7 (Panther) (Apple TV 3.0.2)"; + { + OS_Classification osclass = {"Apple", "Mac OS X", "10.4.X", "media device"}; + match.OS_class.push_back(osclass); + } + matches.push_back(match); + } + { + FingerMatch match; + match.line = -1; + match.OS_name = (char *) "Microsoft Windows 7 Professional SP0 - SP1"; + { + OS_Classification osclass = {"Microsoft", "Windows", "7", "general purpose"}; + match.OS_class.push_back(osclass); + } + matches.push_back(match); + } + { + FingerMatch match; + match.line = -1; + match.OS_name = (char *) "Apple Mac OS X 10.6.8 (Snow Leopard) (Darwin 10.8.0) or iPhone mobile phone (iOS 4.2.1)"; + { + OS_Classification osclass = {"Apple", "Mac OS X", "10.6.X", "general purpose"}; + match.OS_class.push_back(osclass); + } + { + OS_Classification osclass = {"Apple", "iOS", "4.X", "phone"}; + match.OS_class.push_back(osclass); + } + matches.push_back(match); + } + { + FingerMatch match; + match.line = -1; + match.OS_name = (char *) "NetBSD 5.0"; + { + OS_Classification osclass = {"NetBSD", "NetBSD", "5.X", "general purpose"}; + match.OS_class.push_back(osclass); + } + matches.push_back(match); + } + { + FingerMatch match; + match.line = -1; + match.OS_name = (char *) "FreeBSD 6.1-RELEASE"; + { + OS_Classification osclass = {"FreeBSD", "FreeBSD", "6.X", "general purpose"}; + match.OS_class.push_back(osclass); + } + matches.push_back(match); + } + { + FingerMatch match; + match.line = -1; + match.OS_name = (char *) "Linux 2.6.35 - 3.0.0"; + { + OS_Classification osclass = {"Linux", "Linux", "2.6.X", "general purpose"}; + match.OS_class.push_back(osclass); + } + { + OS_Classification osclass = {"Linux", "Linux", "3.X", "general purpose"}; + match.OS_class.push_back(osclass); + } + matches.push_back(match); + } + { + FingerMatch match; + match.line = -1; + match.OS_name = (char *) "Microsoft Windows 7 SP0"; + { + OS_Classification osclass = {"Microsoft", "Windows", "7", "general purpose"}; + match.OS_class.push_back(osclass); + } + matches.push_back(match); + } + { + FingerMatch match; + match.line = -1; + match.OS_name = (char *) "Apple Mac OS X 10.6.8 (Snow Leopard) (Darwin 10.8.0)"; + { + OS_Classification osclass = {"Apple", "Mac OS X", "10.6.X", "general purpose"}; + match.OS_class.push_back(osclass); + } + matches.push_back(match); + } + { + FingerMatch match; + match.line = -1; + match.OS_name = (char *) "Linux 2.6.11 - 2.6.15"; + { + OS_Classification osclass = {"Linux", "Linux", "2.6.X", "general purpose"}; + match.OS_class.push_back(osclass); + } + matches.push_back(match); + } + { + FingerMatch match; + match.line = -1; + match.OS_name = (char *) "Apple Mac OS X 10.6.8 (Snow Leopard) (Darwin 10.8.0)"; + { + OS_Classification osclass = {"Apple", "Mac OS X", "10.6.X", "general purpose"}; + match.OS_class.push_back(osclass); + } + matches.push_back(match); + } + { + FingerMatch match; + match.line = -1; + match.OS_name = (char *) "OpenBSD 3.8"; + { + OS_Classification osclass = {"OpenBSD", "OpenBSD", "3.X", "general purpose"}; + match.OS_class.push_back(osclass); + } + matches.push_back(match); + } + { + FingerMatch match; + match.line = -1; + match.OS_name = (char *) "HP ProCurve 2520G switch"; + { + OS_Classification osclass = {"HP", "embedded", NULL, "switch"}; + match.OS_class.push_back(osclass); + } + matches.push_back(match); + } + { + FingerMatch match; + match.line = -1; + match.OS_name = (char *) "OpenBSD 4.8"; + { + OS_Classification osclass = {"OpenBSD", "OpenBSD", "4.X", "general purpose"}; + match.OS_class.push_back(osclass); + } + matches.push_back(match); + } + { + FingerMatch match; + match.line = -1; + match.OS_name = (char *) "Linux 2.6.39"; + { + OS_Classification osclass = {"Linux", "Linux", "2.6.X", "general purpose"}; + match.OS_class.push_back(osclass); + } + matches.push_back(match); + } + { + FingerMatch match; + match.line = -1; + match.OS_name = (char *) "Linux 2.6.32 - 2.6.35"; + { + OS_Classification osclass = {"Linux", "Linux", "2.6.X", "general purpose"}; + match.OS_class.push_back(osclass); + } + matches.push_back(match); + } + { + FingerMatch match; + match.line = -1; + match.OS_name = (char *) "Cisco 1841 or 2509 router (IOS 12.3 - 15.1)"; + { + OS_Classification osclass = {"Cisco", "IOS", "12.X", "router"}; + match.OS_class.push_back(osclass); + } + { + OS_Classification osclass = {"Cisco", "IOS", "15.X", "router"}; + match.OS_class.push_back(osclass); + } + matches.push_back(match); + } + return matches; +} diff --git a/FingerPrintResults.cc b/FingerPrintResults.cc index 86bc6e31ae..6819be3030 100644 --- a/FingerPrintResults.cc +++ b/FingerPrintResults.cc @@ -104,12 +104,18 @@ FingerPrintResults::FingerPrintResults() { osscan_opentcpport = osscan_closedtcpport = osscan_closedudpport = -1; distance = -1; distance_guess = -1; - FPs = (FingerPrint **) safe_zalloc(o.maxOSTries() * sizeof(FingerPrint *)); maxTimingRatio = 0; - numFPs = 0; } FingerPrintResults::~FingerPrintResults() { +} + +FingerPrintResultsIPv4::FingerPrintResultsIPv4() { + FPs = (FingerPrint **) safe_zalloc(o.maxOSTries() * sizeof(FingerPrint *)); + numFPs = 0; +} + +FingerPrintResultsIPv4::~FingerPrintResultsIPv4() { int i; /* Free OS fingerprints of OS scanning was done */ @@ -121,6 +127,25 @@ FingerPrintResults::~FingerPrintResults() { free(FPs); } +FingerPrintResultsIPv6::FingerPrintResultsIPv6() { + unsigned int i; + + begin_time.tv_sec = 0; + begin_time.tv_usec = 0; + for (i = 0; i < sizeof(fp_responses) / sizeof(*fp_responses); i++) + fp_responses[i] = NULL; + flow_label = 0; +} + +FingerPrintResultsIPv6::~FingerPrintResultsIPv6() { + unsigned int i; + + for (i = 0; i < sizeof(fp_responses) / sizeof(*fp_responses); i++) { + if (fp_responses[i]) + delete fp_responses[i]; + } +} + const struct OS_Classification_Results *FingerPrintResults::getOSClassification() { if (!isClassified) { populateClassification(); isClassified = true; } return &OSR; @@ -178,6 +203,19 @@ const char *FingerPrintResults::OmitSubmissionFP() { return NULL; } +/* IPv6 classification is more robust to errors than IPv4, so apply less + stringent conditions than the general OmitSubmissionFP. */ +const char *FingerPrintResultsIPv6::OmitSubmissionFP() { + static char reason[128]; + + if (o.scan_delay > 500) { // This can screw up the sequence timing + Snprintf(reason, sizeof(reason), "Scan delay (%d) is greater than 500", o.scan_delay); + return reason; + } + + return NULL; +} + /* Goes through fingerprinting results to populate OSR */ void FingerPrintResults::populateClassification() { @@ -196,8 +234,8 @@ void FingerPrintResults::populateClassification() { for(printno = 0; printno < num_matches; printno++) { // a single print may have multiple classifications - for (osclass = prints[printno]->OS_class.begin(); - osclass != prints[printno]->OS_class.end(); + for (osclass = matches[printno]->OS_class.begin(); + osclass != matches[printno]->OS_class.end(); osclass++) { if (!classAlreadyExistsInResults(&*osclass)) { // Then we have to add it ... first ensure we have room @@ -217,7 +255,7 @@ void FingerPrintResults::populateClassification() { // OK, we will add the new class OSR.OSC[OSR.OSC_num_matches] = &*osclass; OSR.OSC_Accuracy[OSR.OSC_num_matches] = accuracy[printno]; - if (accuracy[printno] == 1.0) OSR.OSC_num_perfect_matches++; + if (printno < num_perfect_matches) OSR.OSC_num_perfect_matches++; OSR.OSC_num_matches++; } } diff --git a/FingerPrintResults.h b/FingerPrintResults.h index 378ed25aaa..2dbcd9d960 100644 --- a/FingerPrintResults.h +++ b/FingerPrintResults.h @@ -97,6 +97,7 @@ class FingerPrintResults; #include "nmap.h" #include "global_structures.h" +#include "FPEngine.h" /* Maximum number of results allowed in one of these things ... */ #define MAX_FP_RESULTS 36 @@ -112,11 +113,11 @@ struct OS_Classification_Results { class FingerPrintResults { public: /* For now ... a lot of the data members should be made private */ FingerPrintResults(); - ~FingerPrintResults(); + virtual ~FingerPrintResults(); double accuracy[MAX_FP_RESULTS]; /* Percentage of match (1.0 == perfect match) in same order as pritns[] below */ - FingerPrint *prints[MAX_FP_RESULTS]; /* ptrs to matching references -- + FingerMatch *matches[MAX_FP_RESULTS]; /* ptrs to matching references -- highest accuracy matches first */ int num_perfect_matches; /* Number of 1.0 accuracy matches in prints[] */ int num_matches; /* Total number of matches in prints[] */ @@ -147,14 +148,13 @@ class FingerPrintResults { consistancy standpoint. */ double maxTimingRatio; - FingerPrint **FPs; /* Fingerprint data obtained from host */ - int numFPs; - /* If the fingerprint is of potentially poor quality, we don't want to print it and ask the user to submit it. In that case, the reason for skipping the FP is returned as a static string. If the FP is great and should be printed, NULL is returned. */ - const char *OmitSubmissionFP(); + virtual const char *OmitSubmissionFP(); + + virtual const char *merge_fpr(const Target *currenths, bool isGoodFP, bool wrapit) const = 0; private: bool isClassified; // Whether populateClassification() has been called @@ -165,4 +165,27 @@ class FingerPrintResults { struct OS_Classification_Results OSR; }; +class FingerPrintResultsIPv4 : public FingerPrintResults { +public: + FingerPrint **FPs; /* Fingerprint data obtained from host */ + int numFPs; + + FingerPrintResultsIPv4(); + virtual ~FingerPrintResultsIPv4(); + const char *merge_fpr(const Target *currenths, bool isGoodFP, bool wrapit) const; +}; + +class FingerPrintResultsIPv6 : public FingerPrintResults { +public: + FPResponse *fp_responses[NUM_FP_PROBES_IPv6]; + struct timeval begin_time; + /* The flow label we set in our sent packets, for calculating offsets later. */ + unsigned int flow_label; + + FingerPrintResultsIPv6(); + virtual ~FingerPrintResultsIPv6(); + const char *OmitSubmissionFP(); + const char *merge_fpr(const Target *currenths, bool isGoodFP, bool wrapit) const; +}; + #endif /* FINGERPRINTRESULTS_H */ diff --git a/Makefile.in b/Makefile.in index db9b694226..e7ffa3acea 100644 --- a/Makefile.in +++ b/Makefile.in @@ -17,8 +17,10 @@ NMAPDEVDIR=~/nmap-private-dev export NBASEDIR=@NBASEDIR@ export NSOCKDIR=@NSOCKDIR@ export LIBLUADIR = @LIBLUADIR@ +export LIBLINEARDIR = @LIBLINEARDIR@ export NDIR=$(shell pwd) export LIBLUA_LIBS = @LIBLUA_LIBS@ +export LIBLINEAR_LIBS = @LIBLINEAR_LIBS@ export NCATDIR=@NCATDIR@ CC = @CC@ CXX = @CXX@ @@ -47,7 +49,7 @@ export CFLAGS = $(CXXFLAGS) # CFLAGS = $(DEFS) $(INCLS) STATIC = LDFLAGS = @LDFLAGS@ $(DBGFLAGS) $(STATIC) -LIBS = @LIBNBASE_LIBS@ @LIBNSOCK_LIBS@ @LIBPCRE_LIBS@ @LIBPCAP_LIBS@ $(OPENSSL_LIBS) libnetutil/libnetutil.a @LIBDNET_LIBS@ @LIBLUA_LIBS@ @LIBS@ +LIBS = @LIBNBASE_LIBS@ @LIBNSOCK_LIBS@ @LIBPCRE_LIBS@ @LIBPCAP_LIBS@ $(OPENSSL_LIBS) libnetutil/libnetutil.a @LIBDNET_LIBS@ @LIBLUA_LIBS@ @LIBLINEAR_LIBS@ @LIBS@ OPENSSL_LIBS = @OPENSSL_LIBS@ # LIBS = -lefence @LIBS@ # LIBS = -lrmalloc @LIBS@ @@ -93,20 +95,20 @@ NSE_OBJS+=nse_openssl.o nse_ssl_cert.o endif endif -export SRCS = main.cc nmap.cc targets.cc tcpip.cc nmap_error.cc utils.cc idle_scan.cc osscan.cc osscan2.cc output.cc payload.cc scan_engine.cc timing.cc charpool.cc services.cc protocols.cc nmap_rpc.cc portlist.cc NmapOps.cc TargetGroup.cc Target.cc FingerPrintResults.cc service_scan.cc NmapOutputTable.cc MACLookup.cc nmap_tty.cc nmap_dns.cc traceroute.cc portreasons.cc xml.cc $(NSE_SRC) @COMPAT_SRCS@ +export SRCS = main.cc nmap.cc targets.cc tcpip.cc nmap_error.cc utils.cc idle_scan.cc osscan.cc osscan2.cc FPEngine.cc FPmodel.cc output.cc payload.cc scan_engine.cc timing.cc charpool.cc services.cc protocols.cc nmap_rpc.cc portlist.cc NmapOps.cc TargetGroup.cc Target.cc FingerPrintResults.cc service_scan.cc NmapOutputTable.cc MACLookup.cc nmap_tty.cc nmap_dns.cc traceroute.cc portreasons.cc xml.cc $(NSE_SRC) @COMPAT_SRCS@ -export HDRS = charpool.h FingerPrintResults.h global_structures.h idle_scan.h MACLookup.h nmap_amigaos.h nmap_dns.h nmap_error.h nmap.h NmapOps.h NmapOutputTable.h nmap_rpc.h nmap_tty.h nmap_winconfig.h osscan.h osscan2.h output.h payload.h portlist.h protocols.h scan_engine.h service_scan.h services.h TargetGroup.h Target.h targets.h tcpip.h timing.h utils.h traceroute.h portreasons.h xml.h $(NSE_HDRS) +export HDRS = charpool.h FingerPrintResults.h global_structures.h idle_scan.h MACLookup.h nmap_amigaos.h nmap_dns.h nmap_error.h nmap.h NmapOps.h NmapOutputTable.h nmap_rpc.h nmap_tty.h nmap_winconfig.h osscan.h osscan2.h FPEngine.h output.h payload.h portlist.h protocols.h scan_engine.h service_scan.h services.h TargetGroup.h Target.h targets.h tcpip.h timing.h utils.h traceroute.h portreasons.h xml.h $(NSE_HDRS) -OBJS = main.o nmap.o targets.o tcpip.o nmap_error.o utils.o idle_scan.o osscan.o osscan2.o output.o payload.o scan_engine.o timing.o charpool.o services.o protocols.o nmap_rpc.o portlist.o NmapOps.o TargetGroup.o Target.o FingerPrintResults.o service_scan.o NmapOutputTable.o MACLookup.o nmap_tty.o nmap_dns.o traceroute.o portreasons.o xml.o $(NSE_OBJS) @COMPAT_OBJS@ +OBJS = main.o nmap.o targets.o tcpip.o nmap_error.o utils.o idle_scan.o osscan.o osscan2.o FPEngine.o FPmodel.o output.o payload.o scan_engine.o timing.o charpool.o services.o protocols.o nmap_rpc.o portlist.o NmapOps.o TargetGroup.o Target.o FingerPrintResults.o service_scan.o NmapOutputTable.o MACLookup.o nmap_tty.o nmap_dns.o traceroute.o portreasons.o xml.o $(NSE_OBJS) @COMPAT_OBJS@ # %.o : %.cc -- nope this is a GNU extension .cc.o: $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $< -o $@ -all: @LUA_BUILD@ @PCAP_BUILD@ @PCRE_BUILD@ @DNET_BUILD@ @NBASE_BUILD@ @NSOCK_BUILD@ @NCAT_BUILD@ netutil_build +all: @LUA_BUILD@ @LIBLINEAR_BUILD@ @PCAP_BUILD@ @PCRE_BUILD@ @DNET_BUILD@ @NBASE_BUILD@ @NSOCK_BUILD@ @NCAT_BUILD@ netutil_build $(MAKE) $(TARGET) $(BUILDZENMAP) $(BUILDNDIFF) $(BUILDNPING) -$(TARGET): @LUA_DEPENDS@ @PCAP_DEPENDS@ @PCRE_DEPENDS@ @DNET_DEPENDS@ $(NBASEDIR)/libnbase.a $(NSOCKDIR)/src/libnsock.a libnetutil/libnetutil.a $(OBJS) +$(TARGET): @LUA_DEPENDS@ @LIBLINEAR_DEPENDS@ @PCAP_DEPENDS@ @PCRE_DEPENDS@ @DNET_DEPENDS@ $(NBASEDIR)/libnbase.a $(NSOCKDIR)/src/libnsock.a libnetutil/libnetutil.a $(OBJS) @echo Compiling nmap rm -f $@ $(CXX) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) @@ -138,6 +140,9 @@ ncat_build: $(NCATDIR)/Makefile nbase_build nsock_build $(NCATDIR)/ncat.h lua_build: $(LIBLUADIR)/Makefile @echo Compiling liblua; cd $(LIBLUADIR) && $(MAKE) liblua.a CC="$(CC)" MYCFLAGS="$(CFLAGS) @LUA_CFLAGS@" +liblinear_build: $(LIBLINEARDIR)/Makefile + @echo Compiling liblinear; cd $(LIBLINEARDIR) && $(MAKE) liblinear.a CC="$(CC)" CFLAGS="$(CFLAGS)" + #$(LIBPCAPDIR)/Makefile: # @echo Configuring libpcap; cd $(LIBPCAPDIR); ./configure @@ -166,7 +171,7 @@ release-rpms: web: cd $(NMAPDEVDIR) && $(MAKE) web -clean: @LUA_CLEAN@ @PCAP_CLEAN@ @PCRE_CLEAN@ @DNET_CLEAN@ nsock_clean nbase_clean netutil_clean my_clean @NPING_CLEAN@ @ZENMAP_CLEAN@ @NCAT_CLEAN@ +clean: @LUA_CLEAN@ @LIBLINEAR_CLEAN@ @PCAP_CLEAN@ @PCRE_CLEAN@ @DNET_CLEAN@ nsock_clean nbase_clean netutil_clean my_clean @NPING_CLEAN@ @ZENMAP_CLEAN@ @NCAT_CLEAN@ my_clean: rm -f dependencies.mk makefile.dep @@ -187,6 +192,8 @@ ncat_clean: -cd $(NCATDIR) && $(MAKE) clean lua_clean: -cd $(LIBLUADIR) && $(MAKE) clean +liblinear_clean: + -cd $(LIBLINEARDIR) && $(MAKE) clean zenmap_clean: -cd $(ZENMAPDIR) && $(PYTHON) setup.py clean --all ndiff_clean: @@ -201,6 +208,7 @@ dnet_dist_clean: -cd $(LIBDNETDIR) && $(MAKE) distclean lua_dist_clean: -cd $(LIBLUADIR) && $(MAKE) clean +liblinear_dist_clean: liblinear_clean nbase_dist_clean: -cd $(NBASEDIR) && $(MAKE) distclean nsock_dist_clean: @@ -218,7 +226,7 @@ nping_dist_clean: debugclean: rm -f *.gcov *.gcda *.gcno gmon.out -distclean: my_clean my_distclean @LUA_DIST_CLEAN@ @PCAP_DIST_CLEAN@ @PCRE_DIST_CLEAN@ @DNET_DIST_CLEAN@ @NPING_DIST_CLEAN@ @ZENMAP_DIST_CLEAN@ @NCAT_DIST_CLEAN@ nsock_dist_clean nbase_dist_clean netutil_dist_clean +distclean: my_clean my_distclean @LUA_DIST_CLEAN@ @LIBLINEAR_DIST_CLEAN@ @PCAP_DIST_CLEAN@ @PCRE_DIST_CLEAN@ @DNET_DIST_CLEAN@ @NPING_DIST_CLEAN@ @ZENMAP_DIST_CLEAN@ @NCAT_DIST_CLEAN@ nsock_dist_clean nbase_dist_clean netutil_dist_clean my_distclean: rm -f Makefile Makefile.bak makefile.dep nmap_config.h stamp-h stamp-h.in \ diff --git a/NmapOps.cc b/NmapOps.cc index e202f71b3b..0268036003 100644 --- a/NmapOps.cc +++ b/NmapOps.cc @@ -326,6 +326,7 @@ void NmapOps::Initialize() { ipopt_firsthop = 0; ipopt_lasthop = 0; release_memory = false; + disable_ipv6_os_results = true; topportlevel = -1; #ifndef NOLUA script = 0; @@ -526,7 +527,7 @@ dialog where you can start NPF if you have administrator privileges."; fatal("--min-rate=%g must be less than or equal to --max-rate=%g", min_packet_send_rate, max_packet_send_rate); } - if (af() == AF_INET6 && (generate_random_ips|numdecoys|osscan|bouncescan|fragscan|idlescan)) { + if (af() == AF_INET6 && (generate_random_ips|numdecoys|bouncescan|fragscan|idlescan)) { fatal("Sorry -- IPv6 support is currently only available for TCP, UDP, and SCTP port scans and list scan (-sL). OS detection, random targets and decoys are also not supported with IPv6. Further support is under consideration."); } diff --git a/NmapOps.h b/NmapOps.h index 64511b3404..7916ee282a 100644 --- a/NmapOps.h +++ b/NmapOps.h @@ -187,6 +187,7 @@ class NmapOps { int nogcc; /* Turn off group congestion control with --nogcc */ int generate_random_ips; /* -iR option */ FingerPrintDB *reference_FPs; /* Used in the new OS scan system. */ + std::vector os_labels_ipv6; u16 magic_port; unsigned short magic_port_set; /* Was this set by user? */ @@ -351,6 +352,11 @@ class NmapOps { bool noninteractive; bool release_memory; /* suggest to release memory before quitting. used to find memory leaks. */ + + /* This is a temporary option that disables the printing of IPv6 OS results, + to allow collection of more fingerprints. */ + bool disable_ipv6_os_results; + private: int max_os_tries; int max_rtt_timeout; diff --git a/Target.cc b/Target.cc index 69d654f5ba..087d3084cf 100644 --- a/Target.cc +++ b/Target.cc @@ -113,6 +113,7 @@ void Target::Initialize() { targetname = NULL; memset(&seq, 0, sizeof(seq)); distance = -1; + distance_calculation_method = DIST_METHOD_NONE; FPR = NULL; osscan_flag = OS_NOTPERF; weird_responses = flags = 0; @@ -124,6 +125,7 @@ void Target::Initialize() { targetsocklen = sourcesocklen = nexthopsocklen = 0; directly_connected = -1; targetipstring[0] = '\0'; + sourceipstring[0] = '\0'; nameIPBuf = NULL; memset(&MACaddress, 0, sizeof(MACaddress)); memset(&SrcMACaddress, 0, sizeof(SrcMACaddress)); @@ -177,7 +179,7 @@ void Target::FreeInternal() { /* Creates a "presentation" formatted string out of the IPv4/IPv6 address. Called when the IP changes */ -void Target::GenerateIPString() { +void Target::GenerateTargetIPString() { struct sockaddr_in *sin = (struct sockaddr_in *) &targetsock; #if HAVE_IPV6 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &targetsock; @@ -195,6 +197,26 @@ void Target::GenerateIPString() { } } +/* Creates a "presentation" formatted string out of the IPv4/IPv6 address. + Called when the IP changes */ +void Target::GenerateSourceIPString() { + struct sockaddr_in *sin = (struct sockaddr_in *) &sourcesock; +#if HAVE_IPV6 + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &sourcesock; +#endif + + if (inet_ntop(sin->sin_family, (sin->sin_family == AF_INET)? + (char *) &sin->sin_addr : +#if HAVE_IPV6 + (char *) &sin6->sin6_addr, +#else + (char *) NULL, +#endif + sourceipstring, sizeof(sourceipstring)) == NULL) { + fatal("Failed to convert source address to presentation format!?! Error: %s", strerror(socket_errno())); + } +} + /* Returns the address family of the destination address. */ int Target::af() const { return targetsock.ss_family; @@ -233,7 +255,7 @@ void Target::setTargetSockAddr(const struct sockaddr_storage *ss, size_t ss_len) } memcpy(&targetsock, ss, ss_len); targetsocklen = ss_len; - GenerateIPString(); + GenerateTargetIPString(); /* The ports array needs to know a name too */ ports.setIdStr(targetipstr()); } @@ -286,6 +308,7 @@ void Target::setSourceSockAddr(const struct sockaddr_storage *ss, size_t ss_len) assert(ss_len > 0 && ss_len <= sizeof(*ss)); memcpy(&sourcesock, ss, ss_len); sourcesocklen = ss_len; + GenerateSourceIPString(); } // Returns IPv4 host address or {0} if unavailable. diff --git a/Target.h b/Target.h index d8ced1519c..1545c5fa4f 100644 --- a/Target.h +++ b/Target.h @@ -185,6 +185,8 @@ class Target { const struct in6_addr *v6sourceip() const; /* The IPv4 or IPv6 literal string for the target host */ const char *targetipstr() const { return targetipstring; } + /* The IPv4 or IPv6 literal string for the source address */ + const char *sourceipstr() const { return sourceipstring; } /* Give the name from the last setHostName() call, which should be the name obtained from reverse-resolution (PTR query) of the IP (v4 or v6). If the name has not been set, or was set to NULL, an empty @@ -315,12 +317,15 @@ class Target { private: void Initialize(); void FreeInternal(); // Free memory allocated inside this object - // Creates a "presentation" formatted string out of the IPv4/IPv6 address - void GenerateIPString(); + // Creates a "presentation" formatted string out of the target's IPv4/IPv6 address + void GenerateTargetIPString(); + // Creates a "presentation" formatted string out of the source IPv4/IPv6 address. + void GenerateSourceIPString(); struct sockaddr_storage targetsock, sourcesock, nexthopsock; size_t targetsocklen, sourcesocklen, nexthopsocklen; int directly_connected; // -1 = unset; 0 = no; 1 = yes char targetipstring[INET6_ADDRSTRLEN]; + char sourceipstring[INET6_ADDRSTRLEN]; char *nameIPBuf; /* for the NameIP(void) function to return */ u8 MACaddress[6], SrcMACaddress[6], NextHopMACaddress[6]; bool MACaddress_set, SrcMACaddress_set, NextHopMACaddress_set; diff --git a/configure b/configure index 878d9513c9..38a5d86271 100755 --- a/configure +++ b/configure @@ -606,6 +606,12 @@ NSOCKDIR LIBNBASE_LIBS NBASE_BUILD NBASEDIR +LIBLINEAR_DIST_CLEAN +LIBLINEAR_CLEAN +LIBLINEAR_BUILD +LIBLINEAR_DEPENDS +LIBLINEARDIR +LIBLINEAR_LIBS INSTALLNSE LUA_DIST_CLEAN LUA_CLEAN @@ -741,6 +747,7 @@ with_libpcap with_libpcre with_libdnet with_liblua +with_liblinear with_libnbase with_libnsock with_ncat @@ -1403,6 +1410,28 @@ Optional Packages: --with-liblua=included Use the liblua version included with Nmap --without-liblua Compile without lua (this will exclude all of NSE from compilation) + --with-liblinear=DIR Use an existing (compiled) liblinear from + DIR/include and DIR/lib. + --with-liblinear=included + Use the liblinear version included with Nmap + case "$with_liblinear" in + yes) + ;; + included) + CPPFLAGS="-I\$(top_srcdir)/$LIBLINEARDIR $CPPFLAGS" + LIBLINEAR_LIBS="\$(top_srcdir)/$LIBLINEARDIR/liblinear.a" + LIBLINEAR_DEPENDS="\$(top_srcdir)/$LIBLINEARDIR/liblinear.a" + LIBLINEAR_BUILD="liblinear_build" + LIBLINEAR_CLEAN="liblinear_clean" + LIBLINEAR_DIST_CLEAN="liblinear_dist_clean" + have_liblinear=yes + ;; + *) + CPPFLAGS="-I$with_liblinear/include $CPPFLAGS" + LDFLAGS="-L$with_liblinear/lib $LDFLAGS" + ;; + esac + --with-libnbase=DIR Look for nbase include/libs in DIR --with-libnsock=DIR Compile and link to libnsock in DIR --without-ncat Skip build and installation of Ncat @@ -6797,6 +6826,104 @@ fi + +LIBLINEARDIR=liblinear +have_liblinear=no + +# First we test whether they specified liblinear explicitly + +# Check whether --with-liblinear was given. +if test "${with_liblinear+set}" = set; then : + withval=$with_liblinear; +fi + + +# If they didn't specify it, we try to find it +if test $have_liblinear != yes; then + for ac_header in linear.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "linear.h" "ac_cv_header_linear_h" "$ac_includes_default" +if test "x$ac_cv_header_linear_h" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LINEAR_H 1 +_ACEOF + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for predict in -llinear" >&5 +$as_echo_n "checking for predict in -llinear... " >&6; } +if test "${ac_cv_lib_linear_predict+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-llinear -lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char predict (); +int +main () +{ +return predict (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_linear_predict=yes +else + ac_cv_lib_linear_predict=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_linear_predict" >&5 +$as_echo "$ac_cv_lib_linear_predict" >&6; } +if test "x$ac_cv_lib_linear_predict" = x""yes; then : + have_liblinear=yes; LIBLINEAR_LIBS="-llinear"; break +fi + + +fi + +done + + + LIBLINEAR_DEPENDS="" + LIBLINEAR_BUILD="" + LIBLINEAR_CLEAN="" + LIBLINEAR_DIST_CLEAN="" +fi + +# if we didn't find we use our own +if test $have_liblinear != yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + CPPFLAGS="-I\$(top_srcdir)/$LIBLINEARDIR $CPPFLAGS" + LIBLINEAR_LIBS="\$(top_srcdir)/$LIBLINEARDIR/liblinear.a" + LIBLINEAR_DEPENDS="\$(top_srcdir)/$LIBLINEARDIR/liblinear.a" + LIBLINEAR_BUILD="liblinear_build" + LIBLINEAR_CLEAN="liblinear_clean" + LIBLINEAR_DIST_CLEAN="liblinear_dist_clean" + $as_echo "#define LIBLINEAR_INCLUDED 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if sockaddr{} has sa_len member" >&5 $as_echo_n "checking if sockaddr{} has sa_len member... " >&6; } if test "${ac_cv_sockaddr_has_sa_len+set}" = set; then : diff --git a/configure.ac b/configure.ac index b95a17cd75..f1e1c1d9e8 100644 --- a/configure.ac +++ b/configure.ac @@ -645,6 +645,67 @@ AC_SUBST(LUA_DIST_CLEAN) AC_SUBST(INSTALLNSE) AC_SUBST(CXXFLAGS) + +LIBLINEARDIR=liblinear +have_liblinear=no + +# First we test whether they specified liblinear explicitly +AC_ARG_WITH(liblinear, +AC_HELP_STRING([--with-liblinear=DIR], [Use an existing (compiled) liblinear from DIR/include and DIR/lib.]) +AC_HELP_STRING([--with-liblinear=included], [Use the liblinear version included with Nmap]) +[ case "$with_liblinear" in + yes) + ;; + included) + CPPFLAGS="-I\$(top_srcdir)/$LIBLINEARDIR $CPPFLAGS" + LIBLINEAR_LIBS="\$(top_srcdir)/$LIBLINEARDIR/liblinear.a" + LIBLINEAR_DEPENDS="\$(top_srcdir)/$LIBLINEARDIR/liblinear.a" + LIBLINEAR_BUILD="liblinear_build" + LIBLINEAR_CLEAN="liblinear_clean" + LIBLINEAR_DIST_CLEAN="liblinear_dist_clean" + have_liblinear=yes + ;; + *) + CPPFLAGS="-I$with_liblinear/include $CPPFLAGS" + LDFLAGS="-L$with_liblinear/lib $LDFLAGS" + ;; + esac] +) + +# If they didn't specify it, we try to find it +if test $have_liblinear != yes; then + AC_CHECK_HEADERS([linear.h], + AC_CHECK_LIB(linear, predict, [have_liblinear=yes; LIBLINEAR_LIBS="-llinear"; break],, [-lm]) + ) + + LIBLINEAR_DEPENDS="" + LIBLINEAR_BUILD="" + LIBLINEAR_CLEAN="" + LIBLINEAR_DIST_CLEAN="" +fi + +# if we didn't find we use our own +if test $have_liblinear != yes; then + AC_MSG_RESULT(no) + CPPFLAGS="-I\$(top_srcdir)/$LIBLINEARDIR $CPPFLAGS" + LIBLINEAR_LIBS="\$(top_srcdir)/$LIBLINEARDIR/liblinear.a" + LIBLINEAR_DEPENDS="\$(top_srcdir)/$LIBLINEARDIR/liblinear.a" + LIBLINEAR_BUILD="liblinear_build" + LIBLINEAR_CLEAN="liblinear_clean" + LIBLINEAR_DIST_CLEAN="liblinear_dist_clean" + AC_DEFINE(LIBLINEAR_INCLUDED) +else + AC_MSG_RESULT(yes) +fi + +AC_SUBST(LIBLINEAR_LIBS) +AC_SUBST(LIBLINEARDIR) +AC_SUBST(LIBLINEAR_DEPENDS) +AC_SUBST(LIBLINEAR_BUILD) +AC_SUBST(LIBLINEAR_CLEAN) +AC_SUBST(LIBLINEAR_DIST_CLEAN) + + dnl This test is from the configure.in of Unix Network Programming second dnl edition example code by W. Richard Stevens dnl ################################################################## diff --git a/docs/3rd-party-licenses.txt b/docs/3rd-party-licenses.txt index 24f2346c7a..2aa749a86f 100644 --- a/docs/3rd-party-licenses.txt +++ b/docs/3rd-party-licenses.txt @@ -31,6 +31,8 @@ On all platforms, Nmap is normally linked with: the subdirectory mswin32/OpenSSL. OpenSSL can be disabled by configuring with the --without-openssl configuration directive. http://www.openssl.org/ + o LIBLINEAR. Used for IPv6 OS classifiction. + http://www.csie.ntu.edu.tw/~cjlin/liblinear/ On Windows only, Nmap uses: o WinPcap: libpcap for Windows. The libpcap license applies to WinPcap, @@ -390,6 +392,41 @@ http://www.winpcap.org/misc/copyright.htm. ======== +License of LIBLINEAR + +Copyright (c) 2007-2011 The LIBLINEAR Project. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +3. Neither name of copyright holders nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +======== + License of Python PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 diff --git a/global_structures.h b/global_structures.h index b12ec4629d..9e6f0ccb29 100644 --- a/global_structures.h +++ b/global_structures.h @@ -169,6 +169,14 @@ struct OS_Classification { std::vector cpe; }; +/* A description of an operating system: a human-readable name and a list of + classifications. */ +struct FingerMatch { + int line; /* For reference prints, the line # in nmap-os-db */ + char *OS_name; + std::vector OS_class; +}; + struct FingerTest { const char *name; std::vector results; @@ -176,9 +184,7 @@ struct FingerTest { }; struct FingerPrint { - int line; /* For reference prints, the line # in nmap-os-db */ - char *OS_name; - std::vector OS_class; + FingerMatch match; std::vector tests; const FingerTest *gettestbyname(const char *name) const; FingerPrint(); diff --git a/liblinear/COPYRIGHT b/liblinear/COPYRIGHT new file mode 100644 index 0000000000..71c0ad7f9d --- /dev/null +++ b/liblinear/COPYRIGHT @@ -0,0 +1,31 @@ + +Copyright (c) 2007-2011 The LIBLINEAR Project. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +3. Neither name of copyright holders nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/liblinear/Makefile b/liblinear/Makefile new file mode 100644 index 0000000000..2c84a16925 --- /dev/null +++ b/liblinear/Makefile @@ -0,0 +1,36 @@ +CXX ?= g++ +CC ?= gcc +CFLAGS = -Wall -Wconversion -O3 -fPIC +LIBS = blas/blas.a +SHVER = 1 +AR = ar +RANLIB = ranlib +#LIBS = -lblas + +all: train predict + +lib: linear.o tron.o blas/blas.a + $(CXX) -shared -dynamiclib linear.o tron.o blas/blas.a -o liblinear.so.$(SHVER) + +liblinear.a: linear.o tron.o blas/blas.a + $(AR) rcv liblinear.a linear.o tron.o blas/*.o + $(RANLIB) liblinear.a + +train: tron.o linear.o train.c blas/blas.a + $(CXX) $(CFLAGS) -o train train.c tron.o linear.o $(LIBS) + +predict: tron.o linear.o predict.c blas/blas.a + $(CXX) $(CFLAGS) -o predict predict.c tron.o linear.o $(LIBS) + +tron.o: tron.cpp tron.h + $(CXX) $(CFLAGS) -c -o tron.o tron.cpp + +linear.o: linear.cpp linear.h + $(CXX) $(CFLAGS) -c -o linear.o linear.cpp + +blas/blas.a: + cd blas; make OPTFLAGS='$(CFLAGS)' CC='$(CC)'; + +clean: + cd blas; make clean + rm -f *~ tron.o linear.o train predict liblinear.so.$(SHVER) liblinear.a diff --git a/liblinear/Makefile.win b/liblinear/Makefile.win new file mode 100644 index 0000000000..c5c721fae9 --- /dev/null +++ b/liblinear/Makefile.win @@ -0,0 +1,30 @@ +#You must ensure nmake.exe, cl.exe, link.exe are in system path. +#VCVARS32.bat +#Under dosbox prompt +#nmake -f Makefile.win + +########################################## +CXXC = cl.exe +CFLAGS = -nologo -O2 -EHsc -I. -D __WIN32__ -D _CRT_SECURE_NO_DEPRECATE +TARGET = windows + +all: $(TARGET)\train.exe $(TARGET)\predict.exe + +$(TARGET)\train.exe: tron.obj linear.obj train.c blas\*.c + $(CXX) $(CFLAGS) -Fe$(TARGET)\train.exe tron.obj linear.obj train.c blas\*.c + +$(TARGET)\predict.exe: tron.obj linear.obj predict.c blas\*.c + $(CXX) $(CFLAGS) -Fe$(TARGET)\predict.exe tron.obj linear.obj predict.c blas\*.c + +linear.obj: linear.cpp linear.h + $(CXX) $(CFLAGS) -c linear.cpp + +tron.obj: tron.cpp tron.h + $(CXX) $(CFLAGS) -c tron.cpp + +lib: linear.cpp linear.h linear.def tron.obj + $(CXX) $(CFLAGS) -LD linear.cpp tron.obj blas\*.c -Fe$(TARGET)\liblinear -link -DEF:linear.def + +clean: + -erase /Q *.obj $(TARGET)\. + diff --git a/liblinear/README b/liblinear/README new file mode 100644 index 0000000000..4e45c2e359 --- /dev/null +++ b/liblinear/README @@ -0,0 +1,485 @@ +LIBLINEAR is a simple package for solving large-scale regularized +linear classification. It currently supports L2-regularized logistic +regression/L2-loss support vector classification/L1-loss support vector +classification, and L1-regularized L2-loss support vector classification/ +logistic regression. This document explains the usage of LIBLINEAR. + +To get started, please read the ``Quick Start'' section first. +For developers, please check the ``Library Usage'' section to learn +how to integrate LIBLINEAR in your software. + +Table of Contents +================= + +- When to use LIBLINEAR but not LIBSVM +- Quick Start +- Installation +- `train' Usage +- `predict' Usage +- Examples +- Library Usage +- Building Windows Binaries +- Additional Information +- MATLAB/OCTAVE interface +- PYTHON interface + +When to use LIBLINEAR but not LIBSVM +==================================== + +There are some large data for which with/without nonlinear mappings +gives similar performances. Without using kernels, one can +efficiently train a much larger set via a linear classifier. These +data usually have a large number of features. Document classification +is an example. + +Warning: While generally liblinear is very fast, its default solver +may be slow under certain situations (e.g., data not scaled or C is +large). See Appendix B of our SVM guide about how to handle such +cases. +http://www.csie.ntu.edu.tw/~cjlin/papers/guide/guide.pdf + +Warning: If you are a beginner and your data sets are not large, you +should consider LIBSVM first. + +LIBSVM page: +http://www.csie.ntu.edu.tw/~cjlin/libsvm + + +Quick Start +=========== + +See the section ``Installation'' for installing LIBLINEAR. + +After installation, there are programs `train' and `predict' for +training and testing, respectively. + +About the data format, please check the README file of LIBSVM. Note +that feature index must start from 1 (but not 0). + +A sample classification data included in this package is `heart_scale'. + +Type `train heart_scale', and the program will read the training +data and output the model file `heart_scale.model'. If you have a test +set called heart_scale.t, then type `predict heart_scale.t +heart_scale.model output' to see the prediction accuracy. The `output' +file contains the predicted class labels. + +For more information about `train' and `predict', see the sections +`train' Usage and `predict' Usage. + +To obtain good performances, sometimes one needs to scale the +data. Please check the program `svm-scale' of LIBSVM. For large and +sparse data, use `-l 0' to keep the sparsity. + +Installation +============ + +On Unix systems, type `make' to build the `train' and `predict' +programs. Run them without arguments to show the usages. + +On other systems, consult `Makefile' to build them (e.g., see +'Building Windows binaries' in this file) or use the pre-built +binaries (Windows binaries are in the directory `windows'). + +This software uses some level-1 BLAS subroutines. The needed functions are +included in this package. If a BLAS library is available on your +machine, you may use it by modifying the Makefile: Unmark the following line + + #LIBS ?= -lblas + +and mark + + LIBS ?= blas/blas.a + +`train' Usage +============= + +Usage: train [options] training_set_file [model_file] +options: +-s type : set type of solver (default 1) + 0 -- L2-regularized logistic regression (primal) + 1 -- L2-regularized L2-loss support vector classification (dual) + 2 -- L2-regularized L2-loss support vector classification (primal) + 3 -- L2-regularized L1-loss support vector classification (dual) + 4 -- multi-class support vector classification by Crammer and Singer + 5 -- L1-regularized L2-loss support vector classification + 6 -- L1-regularized logistic regression + 7 -- L2-regularized logistic regression (dual) +-c cost : set the parameter C (default 1) +-e epsilon : set tolerance of termination criterion + -s 0 and 2 + |f'(w)|_2 <= eps*min(pos,neg)/l*|f'(w0)|_2, + where f is the primal function and pos/neg are # of + positive/negative data (default 0.01) + -s 1, 3, 4 and 7 + Dual maximal violation <= eps; similar to libsvm (default 0.1) + -s 5 and 6 + |f'(w)|_inf <= eps*min(pos,neg)/l*|f'(w0)|_inf, + where f is the primal function (default 0.01) +-B bias : if bias >= 0, instance x becomes [x; bias]; if < 0, no bias term added (default -1) +-wi weight: weights adjust the parameter C of different classes (see README for details) +-v n: n-fold cross validation mode +-q : quiet mode (no outputs) + +Option -v randomly splits the data into n parts and calculates cross +validation accuracy on them. + +Formulations: + +For L2-regularized logistic regression (-s 0), we solve + +min_w w^Tw/2 + C \sum log(1 + exp(-y_i w^Tx_i)) + +For L2-regularized L2-loss SVC dual (-s 1), we solve + +min_alpha 0.5(alpha^T (Q + I/2/C) alpha) - e^T alpha + s.t. 0 <= alpha_i, + +For L2-regularized L2-loss SVC (-s 2), we solve + +min_w w^Tw/2 + C \sum max(0, 1- y_i w^Tx_i)^2 + +For L2-regularized L1-loss SVC dual (-s 3), we solve + +min_alpha 0.5(alpha^T Q alpha) - e^T alpha + s.t. 0 <= alpha_i <= C, + +For L1-regularized L2-loss SVC (-s 5), we solve + +min_w \sum |w_j| + C \sum max(0, 1- y_i w^Tx_i)^2 + +For L1-regularized logistic regression (-s 6), we solve + +min_w \sum |w_j| + C \sum log(1 + exp(-y_i w^Tx_i)) + +where + +Q is a matrix with Q_ij = y_i y_j x_i^T x_j. + +For L2-regularized logistic regression (-s 7), we solve + +min_alpha 0.5(alpha^T Q alpha) + \sum alpha_i*log(alpha_i) + \sum (C-alpha_i)*log(C-alpha_i) - a constant + s.t. 0 <= alpha_i <= C, + +If bias >= 0, w becomes [w; w_{n+1}] and x becomes [x; bias]. + +The primal-dual relationship implies that -s 1 and -s 2 give the same +model, and -s 0 and -s 7 give the same. + +We implement 1-vs-the rest multi-class strategy. In training i +vs. non_i, their C parameters are (weight from -wi)*C and C, +respectively. If there are only two classes, we train only one +model. Thus weight1*C vs. weight2*C is used. See examples below. + +We also implement multi-class SVM by Crammer and Singer (-s 4): + +min_{w_m, \xi_i} 0.5 \sum_m ||w_m||^2 + C \sum_i \xi_i + s.t. w^T_{y_i} x_i - w^T_m x_i >= \e^m_i - \xi_i \forall m,i + +where e^m_i = 0 if y_i = m, + e^m_i = 1 if y_i != m, + +Here we solve the dual problem: + +min_{\alpha} 0.5 \sum_m ||w_m(\alpha)||^2 + \sum_i \sum_m e^m_i alpha^m_i + s.t. \alpha^m_i <= C^m_i \forall m,i , \sum_m \alpha^m_i=0 \forall i + +where w_m(\alpha) = \sum_i \alpha^m_i x_i, +and C^m_i = C if m = y_i, + C^m_i = 0 if m != y_i. + +`predict' Usage +=============== + +Usage: predict [options] test_file model_file output_file +options: +-b probability_estimates: whether to predict probability estimates, 0 or 1 (default 0) + +Examples +======== + +> train data_file + +Train linear SVM with L2-loss function. + +> train -s 0 data_file + +Train a logistic regression model. + +> train -v 5 -e 0.001 data_file + +Do five-fold cross-validation using L2-loss svm. +Use a smaller stopping tolerance 0.001 than the default +0.1 if you want more accurate solutions. + +> train -c 10 -w1 2 -w2 5 -w3 2 four_class_data_file + +Train four classifiers: +positive negative Cp Cn +class 1 class 2,3,4. 20 10 +class 2 class 1,3,4. 50 10 +class 3 class 1,2,4. 20 10 +class 4 class 1,2,3. 10 10 + +> train -c 10 -w3 1 -w2 5 two_class_data_file + +If there are only two classes, we train ONE model. +The C values for the two classes are 10 and 50. + +> predict -b 1 test_file data_file.model output_file + +Output probability estimates (for logistic regression only). + +Library Usage +============= + +- Function: model* train(const struct problem *prob, + const struct parameter *param); + + This function constructs and returns a linear classification model + according to the given training data and parameters. + + struct problem describes the problem: + + struct problem + { + int l, n; + int *y; + struct feature_node **x; + double bias; + }; + + where `l' is the number of training data. If bias >= 0, we assume + that one additional feature is added to the end of each data + instance. `n' is the number of feature (including the bias feature + if bias >= 0). `y' is an array containing the target values. And + `x' is an array of pointers, + each of which points to a sparse representation (array of feature_node) of one + training vector. + + For example, if we have the following training data: + + LABEL ATTR1 ATTR2 ATTR3 ATTR4 ATTR5 + ----- ----- ----- ----- ----- ----- + 1 0 0.1 0.2 0 0 + 2 0 0.1 0.3 -1.2 0 + 1 0.4 0 0 0 0 + 2 0 0.1 0 1.4 0.5 + 3 -0.1 -0.2 0.1 1.1 0.1 + + and bias = 1, then the components of problem are: + + l = 5 + n = 6 + + y -> 1 2 1 2 3 + + x -> [ ] -> (2,0.1) (3,0.2) (6,1) (-1,?) + [ ] -> (2,0.1) (3,0.3) (4,-1.2) (6,1) (-1,?) + [ ] -> (1,0.4) (6,1) (-1,?) + [ ] -> (2,0.1) (4,1.4) (5,0.5) (6,1) (-1,?) + [ ] -> (1,-0.1) (2,-0.2) (3,0.1) (4,1.1) (5,0.1) (6,1) (-1,?) + + struct parameter describes the parameters of a linear classification model: + + struct parameter + { + int solver_type; + + /* these are for training only */ + double eps; /* stopping criteria */ + double C; + int nr_weight; + int *weight_label; + double* weight; + }; + + solver_type can be one of L2R_LR, L2R_L2LOSS_SVC_DUAL, L2R_L2LOSS_SVC, L2R_L1LOSS_SVC_DUAL, MCSVM_CS, L1R_L2LOSS_SVC, L1R_LR, L2R_LR_DUAL. + + L2R_LR L2-regularized logistic regression (primal) + L2R_L2LOSS_SVC_DUAL L2-regularized L2-loss support vector classification (dual) + L2R_L2LOSS_SVC L2-regularized L2-loss support vector classification (primal) + L2R_L1LOSS_SVC_DUAL L2-regularized L1-loss support vector classification (dual) + MCSVM_CS multi-class support vector classification by Crammer and Singer + L1R_L2LOSS_SVC L1-regularized L2-loss support vector classification + L1R_LR L1-regularized logistic regression + L2R_LR_DUAL L2-regularized logistic regression (dual) + + C is the cost of constraints violation. + eps is the stopping criterion. + + nr_weight, weight_label, and weight are used to change the penalty + for some classes (If the weight for a class is not changed, it is + set to 1). This is useful for training classifier using unbalanced + input data or with asymmetric misclassification cost. + + nr_weight is the number of elements in the array weight_label and + weight. Each weight[i] corresponds to weight_label[i], meaning that + the penalty of class weight_label[i] is scaled by a factor of weight[i]. + + If you do not want to change penalty for any of the classes, + just set nr_weight to 0. + + *NOTE* To avoid wrong parameters, check_parameter() should be + called before train(). + + struct model stores the model obtained from the training procedure: + + struct model + { + struct parameter param; + int nr_class; /* number of classes */ + int nr_feature; + double *w; + int *label; /* label of each class */ + double bias; + }; + + param describes the parameters used to obtain the model. + + nr_class and nr_feature are the number of classes and features, respectively. + + The nr_feature*nr_class array w gives feature weights. We use one + against the rest for multi-class classification, so each feature + index corresponds to nr_class weight values. Weights are + organized in the following way + + +------------------+------------------+------------+ + | nr_class weights | nr_class weights | ... + | for 1st feature | for 2nd feature | + +------------------+------------------+------------+ + + If bias >= 0, x becomes [x; bias]. The number of features is + increased by one, so w is a (nr_feature+1)*nr_class array. The + value of bias is stored in the variable bias. + + The array label stores class labels. + +- Function: void cross_validation(const problem *prob, const parameter *param, int nr_fold, int *target); + + This function conducts cross validation. Data are separated to + nr_fold folds. Under given parameters, sequentially each fold is + validated using the model from training the remaining. Predicted + labels in the validation process are stored in the array called + target. + + The format of prob is same as that for train(). + +- Function: int predict(const model *model_, const feature_node *x); + + This functions classifies a test vector using the given + model. The predicted label is returned. + +- Function: int predict_values(const struct model *model_, + const struct feature_node *x, double* dec_values); + + This function gives nr_w decision values in the array + dec_values. nr_w is 1 if there are two classes except multi-class + svm by Crammer and Singer (-s 4), and is the number of classes otherwise. + + We implement one-vs-the rest multi-class strategy (-s 0,1,2,3) and + multi-class svm by Crammer and Singer (-s 4) for multi-class SVM. + The class with the highest decision value is returned. + +- Function: int predict_probability(const struct model *model_, + const struct feature_node *x, double* prob_estimates); + + This function gives nr_class probability estimates in the array + prob_estimates. nr_class can be obtained from the function + get_nr_class. The class with the highest probability is + returned. Currently, we support only the probability outputs of + logistic regression. + +- Function: int get_nr_feature(const model *model_); + + The function gives the number of attributes of the model. + +- Function: int get_nr_class(const model *model_); + + The function gives the number of classes of the model. + +- Function: void get_labels(const model *model_, int* label); + + This function outputs the name of labels into an array called label. + +- Function: const char *check_parameter(const struct problem *prob, + const struct parameter *param); + + This function checks whether the parameters are within the feasible + range of the problem. This function should be called before calling + train() and cross_validation(). It returns NULL if the + parameters are feasible, otherwise an error message is returned. + +- Function: int save_model(const char *model_file_name, + const struct model *model_); + + This function saves a model to a file; returns 0 on success, or -1 + if an error occurs. + +- Function: struct model *load_model(const char *model_file_name); + + This function returns a pointer to the model read from the file, + or a null pointer if the model could not be loaded. + +- Function: void free_model_content(struct model *model_ptr); + + This function frees the memory used by the entries in a model structure. + +- Function: void free_and_destroy_model(struct model **model_ptr_ptr); + + This function frees the memory used by a model and destroys the model + structure. + +- Function: void destroy_param(struct parameter *param); + + This function frees the memory used by a parameter set. + +- Function: void set_print_string_function(void (*print_func)(const char *)); + + Users can specify their output format by a function. Use + set_print_string_function(NULL); + for default printing to stdout. + +Building Windows Binaries +========================= + +Windows binaries are in the directory `windows'. To build them via +Visual C++, use the following steps: + +1. Open a dos command box and change to liblinear directory. If +environment variables of VC++ have not been set, type + +"C:\Program Files\Microsoft Visual Studio 10.0\VC\bin\vcvars32.bat" + +You may have to modify the above command according which version of +VC++ or where it is installed. + +2. Type + +nmake -f Makefile.win clean all + + +MATLAB/OCTAVE Interface +======================= + +Please check the file README in the directory `matlab'. + +PYTHON Interface +================ + +Please check the file README in the directory `python'. + +Additional Information +====================== + +If you find LIBLINEAR helpful, please cite it as + +R.-E. Fan, K.-W. Chang, C.-J. Hsieh, X.-R. Wang, and C.-J. Lin. +LIBLINEAR: A Library for Large Linear Classification, Journal of +Machine Learning Research 9(2008), 1871-1874. Software available at +http://www.csie.ntu.edu.tw/~cjlin/liblinear + +For any questions and comments, please send your email to +cjlin@csie.ntu.edu.tw + + diff --git a/liblinear/blas/Makefile b/liblinear/blas/Makefile new file mode 100644 index 0000000000..2be0186ef7 --- /dev/null +++ b/liblinear/blas/Makefile @@ -0,0 +1,22 @@ +AR = ar rcv +RANLIB = ranlib + +HEADERS = blas.h blas.h blasp.h +FILES = dnrm2.o daxpy.o ddot.o dscal.o + +CFLAGS = $(OPTFLAGS) +FFLAGS = $(OPTFLAGS) + +blas: $(FILES) $(HEADERS) + $(AR) blas.a $(FILES) + $(RANLIB) blas.a + +clean: + - rm -f *.o + - rm -f *.a + - rm -f *~ + +.c.o: + $(CC) $(CFLAGS) -c $*.c + + diff --git a/liblinear/blas/blas.h b/liblinear/blas/blas.h new file mode 100644 index 0000000000..558893a043 --- /dev/null +++ b/liblinear/blas/blas.h @@ -0,0 +1,25 @@ +/* blas.h -- C header file for BLAS Ver 1.0 */ +/* Jesse Bennett March 23, 2000 */ + +/** barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed." + + - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) */ + +#ifndef BLAS_INCLUDE +#define BLAS_INCLUDE + +/* Data types specific to BLAS implementation */ +typedef struct { float r, i; } fcomplex; +typedef struct { double r, i; } dcomplex; +typedef int blasbool; + +#include "blasp.h" /* Prototypes for all BLAS functions */ + +#define FALSE 0 +#define TRUE 1 + +/* Macro functions */ +#define MIN(a,b) ((a) <= (b) ? (a) : (b)) +#define MAX(a,b) ((a) >= (b) ? (a) : (b)) + +#endif diff --git a/liblinear/blas/blasp.h b/liblinear/blas/blasp.h new file mode 100644 index 0000000000..745836db87 --- /dev/null +++ b/liblinear/blas/blasp.h @@ -0,0 +1,430 @@ +/* blasp.h -- C prototypes for BLAS Ver 1.0 */ +/* Jesse Bennett March 23, 2000 */ + +/* Functions listed in alphabetical order */ + +#ifdef F2C_COMPAT + +void cdotc_(fcomplex *dotval, int *n, fcomplex *cx, int *incx, + fcomplex *cy, int *incy); + +void cdotu_(fcomplex *dotval, int *n, fcomplex *cx, int *incx, + fcomplex *cy, int *incy); + +double sasum_(int *n, float *sx, int *incx); + +double scasum_(int *n, fcomplex *cx, int *incx); + +double scnrm2_(int *n, fcomplex *x, int *incx); + +double sdot_(int *n, float *sx, int *incx, float *sy, int *incy); + +double snrm2_(int *n, float *x, int *incx); + +void zdotc_(dcomplex *dotval, int *n, dcomplex *cx, int *incx, + dcomplex *cy, int *incy); + +void zdotu_(dcomplex *dotval, int *n, dcomplex *cx, int *incx, + dcomplex *cy, int *incy); + +#else + +fcomplex cdotc_(int *n, fcomplex *cx, int *incx, fcomplex *cy, int *incy); + +fcomplex cdotu_(int *n, fcomplex *cx, int *incx, fcomplex *cy, int *incy); + +float sasum_(int *n, float *sx, int *incx); + +float scasum_(int *n, fcomplex *cx, int *incx); + +float scnrm2_(int *n, fcomplex *x, int *incx); + +float sdot_(int *n, float *sx, int *incx, float *sy, int *incy); + +float snrm2_(int *n, float *x, int *incx); + +dcomplex zdotc_(int *n, dcomplex *cx, int *incx, dcomplex *cy, int *incy); + +dcomplex zdotu_(int *n, dcomplex *cx, int *incx, dcomplex *cy, int *incy); + +#endif + +/* Remaining functions listed in alphabetical order */ + +int caxpy_(int *n, fcomplex *ca, fcomplex *cx, int *incx, fcomplex *cy, + int *incy); + +int ccopy_(int *n, fcomplex *cx, int *incx, fcomplex *cy, int *incy); + +int cgbmv_(char *trans, int *m, int *n, int *kl, int *ku, + fcomplex *alpha, fcomplex *a, int *lda, fcomplex *x, int *incx, + fcomplex *beta, fcomplex *y, int *incy); + +int cgemm_(char *transa, char *transb, int *m, int *n, int *k, + fcomplex *alpha, fcomplex *a, int *lda, fcomplex *b, int *ldb, + fcomplex *beta, fcomplex *c, int *ldc); + +int cgemv_(char *trans, int *m, int *n, fcomplex *alpha, fcomplex *a, + int *lda, fcomplex *x, int *incx, fcomplex *beta, fcomplex *y, + int *incy); + +int cgerc_(int *m, int *n, fcomplex *alpha, fcomplex *x, int *incx, + fcomplex *y, int *incy, fcomplex *a, int *lda); + +int cgeru_(int *m, int *n, fcomplex *alpha, fcomplex *x, int *incx, + fcomplex *y, int *incy, fcomplex *a, int *lda); + +int chbmv_(char *uplo, int *n, int *k, fcomplex *alpha, fcomplex *a, + int *lda, fcomplex *x, int *incx, fcomplex *beta, fcomplex *y, + int *incy); + +int chemm_(char *side, char *uplo, int *m, int *n, fcomplex *alpha, + fcomplex *a, int *lda, fcomplex *b, int *ldb, fcomplex *beta, + fcomplex *c, int *ldc); + +int chemv_(char *uplo, int *n, fcomplex *alpha, fcomplex *a, int *lda, + fcomplex *x, int *incx, fcomplex *beta, fcomplex *y, int *incy); + +int cher_(char *uplo, int *n, float *alpha, fcomplex *x, int *incx, + fcomplex *a, int *lda); + +int cher2_(char *uplo, int *n, fcomplex *alpha, fcomplex *x, int *incx, + fcomplex *y, int *incy, fcomplex *a, int *lda); + +int cher2k_(char *uplo, char *trans, int *n, int *k, fcomplex *alpha, + fcomplex *a, int *lda, fcomplex *b, int *ldb, float *beta, + fcomplex *c, int *ldc); + +int cherk_(char *uplo, char *trans, int *n, int *k, float *alpha, + fcomplex *a, int *lda, float *beta, fcomplex *c, int *ldc); + +int chpmv_(char *uplo, int *n, fcomplex *alpha, fcomplex *ap, fcomplex *x, + int *incx, fcomplex *beta, fcomplex *y, int *incy); + +int chpr_(char *uplo, int *n, float *alpha, fcomplex *x, int *incx, + fcomplex *ap); + +int chpr2_(char *uplo, int *n, fcomplex *alpha, fcomplex *x, int *incx, + fcomplex *y, int *incy, fcomplex *ap); + +int crotg_(fcomplex *ca, fcomplex *cb, float *c, fcomplex *s); + +int cscal_(int *n, fcomplex *ca, fcomplex *cx, int *incx); + +int csscal_(int *n, float *sa, fcomplex *cx, int *incx); + +int cswap_(int *n, fcomplex *cx, int *incx, fcomplex *cy, int *incy); + +int csymm_(char *side, char *uplo, int *m, int *n, fcomplex *alpha, + fcomplex *a, int *lda, fcomplex *b, int *ldb, fcomplex *beta, + fcomplex *c, int *ldc); + +int csyr2k_(char *uplo, char *trans, int *n, int *k, fcomplex *alpha, + fcomplex *a, int *lda, fcomplex *b, int *ldb, fcomplex *beta, + fcomplex *c, int *ldc); + +int csyrk_(char *uplo, char *trans, int *n, int *k, fcomplex *alpha, + fcomplex *a, int *lda, fcomplex *beta, fcomplex *c, int *ldc); + +int ctbmv_(char *uplo, char *trans, char *diag, int *n, int *k, + fcomplex *a, int *lda, fcomplex *x, int *incx); + +int ctbsv_(char *uplo, char *trans, char *diag, int *n, int *k, + fcomplex *a, int *lda, fcomplex *x, int *incx); + +int ctpmv_(char *uplo, char *trans, char *diag, int *n, fcomplex *ap, + fcomplex *x, int *incx); + +int ctpsv_(char *uplo, char *trans, char *diag, int *n, fcomplex *ap, + fcomplex *x, int *incx); + +int ctrmm_(char *side, char *uplo, char *transa, char *diag, int *m, + int *n, fcomplex *alpha, fcomplex *a, int *lda, fcomplex *b, + int *ldb); + +int ctrmv_(char *uplo, char *trans, char *diag, int *n, fcomplex *a, + int *lda, fcomplex *x, int *incx); + +int ctrsm_(char *side, char *uplo, char *transa, char *diag, int *m, + int *n, fcomplex *alpha, fcomplex *a, int *lda, fcomplex *b, + int *ldb); + +int ctrsv_(char *uplo, char *trans, char *diag, int *n, fcomplex *a, + int *lda, fcomplex *x, int *incx); + +int daxpy_(int *n, double *sa, double *sx, int *incx, double *sy, + int *incy); + +int dcopy_(int *n, double *sx, int *incx, double *sy, int *incy); + +int dgbmv_(char *trans, int *m, int *n, int *kl, int *ku, + double *alpha, double *a, int *lda, double *x, int *incx, + double *beta, double *y, int *incy); + +int dgemm_(char *transa, char *transb, int *m, int *n, int *k, + double *alpha, double *a, int *lda, double *b, int *ldb, + double *beta, double *c, int *ldc); + +int dgemv_(char *trans, int *m, int *n, double *alpha, double *a, + int *lda, double *x, int *incx, double *beta, double *y, + int *incy); + +int dger_(int *m, int *n, double *alpha, double *x, int *incx, + double *y, int *incy, double *a, int *lda); + +int drot_(int *n, double *sx, int *incx, double *sy, int *incy, + double *c, double *s); + +int drotg_(double *sa, double *sb, double *c, double *s); + +int dsbmv_(char *uplo, int *n, int *k, double *alpha, double *a, + int *lda, double *x, int *incx, double *beta, double *y, + int *incy); + +int dscal_(int *n, double *sa, double *sx, int *incx); + +int dspmv_(char *uplo, int *n, double *alpha, double *ap, double *x, + int *incx, double *beta, double *y, int *incy); + +int dspr_(char *uplo, int *n, double *alpha, double *x, int *incx, + double *ap); + +int dspr2_(char *uplo, int *n, double *alpha, double *x, int *incx, + double *y, int *incy, double *ap); + +int dswap_(int *n, double *sx, int *incx, double *sy, int *incy); + +int dsymm_(char *side, char *uplo, int *m, int *n, double *alpha, + double *a, int *lda, double *b, int *ldb, double *beta, + double *c, int *ldc); + +int dsymv_(char *uplo, int *n, double *alpha, double *a, int *lda, + double *x, int *incx, double *beta, double *y, int *incy); + +int dsyr_(char *uplo, int *n, double *alpha, double *x, int *incx, + double *a, int *lda); + +int dsyr2_(char *uplo, int *n, double *alpha, double *x, int *incx, + double *y, int *incy, double *a, int *lda); + +int dsyr2k_(char *uplo, char *trans, int *n, int *k, double *alpha, + double *a, int *lda, double *b, int *ldb, double *beta, + double *c, int *ldc); + +int dsyrk_(char *uplo, char *trans, int *n, int *k, double *alpha, + double *a, int *lda, double *beta, double *c, int *ldc); + +int dtbmv_(char *uplo, char *trans, char *diag, int *n, int *k, + double *a, int *lda, double *x, int *incx); + +int dtbsv_(char *uplo, char *trans, char *diag, int *n, int *k, + double *a, int *lda, double *x, int *incx); + +int dtpmv_(char *uplo, char *trans, char *diag, int *n, double *ap, + double *x, int *incx); + +int dtpsv_(char *uplo, char *trans, char *diag, int *n, double *ap, + double *x, int *incx); + +int dtrmm_(char *side, char *uplo, char *transa, char *diag, int *m, + int *n, double *alpha, double *a, int *lda, double *b, + int *ldb); + +int dtrmv_(char *uplo, char *trans, char *diag, int *n, double *a, + int *lda, double *x, int *incx); + +int dtrsm_(char *side, char *uplo, char *transa, char *diag, int *m, + int *n, double *alpha, double *a, int *lda, double *b, + int *ldb); + +int dtrsv_(char *uplo, char *trans, char *diag, int *n, double *a, + int *lda, double *x, int *incx); + + +int saxpy_(int *n, float *sa, float *sx, int *incx, float *sy, int *incy); + +int scopy_(int *n, float *sx, int *incx, float *sy, int *incy); + +int sgbmv_(char *trans, int *m, int *n, int *kl, int *ku, + float *alpha, float *a, int *lda, float *x, int *incx, + float *beta, float *y, int *incy); + +int sgemm_(char *transa, char *transb, int *m, int *n, int *k, + float *alpha, float *a, int *lda, float *b, int *ldb, + float *beta, float *c, int *ldc); + +int sgemv_(char *trans, int *m, int *n, float *alpha, float *a, + int *lda, float *x, int *incx, float *beta, float *y, + int *incy); + +int sger_(int *m, int *n, float *alpha, float *x, int *incx, + float *y, int *incy, float *a, int *lda); + +int srot_(int *n, float *sx, int *incx, float *sy, int *incy, + float *c, float *s); + +int srotg_(float *sa, float *sb, float *c, float *s); + +int ssbmv_(char *uplo, int *n, int *k, float *alpha, float *a, + int *lda, float *x, int *incx, float *beta, float *y, + int *incy); + +int sscal_(int *n, float *sa, float *sx, int *incx); + +int sspmv_(char *uplo, int *n, float *alpha, float *ap, float *x, + int *incx, float *beta, float *y, int *incy); + +int sspr_(char *uplo, int *n, float *alpha, float *x, int *incx, + float *ap); + +int sspr2_(char *uplo, int *n, float *alpha, float *x, int *incx, + float *y, int *incy, float *ap); + +int sswap_(int *n, float *sx, int *incx, float *sy, int *incy); + +int ssymm_(char *side, char *uplo, int *m, int *n, float *alpha, + float *a, int *lda, float *b, int *ldb, float *beta, + float *c, int *ldc); + +int ssymv_(char *uplo, int *n, float *alpha, float *a, int *lda, + float *x, int *incx, float *beta, float *y, int *incy); + +int ssyr_(char *uplo, int *n, float *alpha, float *x, int *incx, + float *a, int *lda); + +int ssyr2_(char *uplo, int *n, float *alpha, float *x, int *incx, + float *y, int *incy, float *a, int *lda); + +int ssyr2k_(char *uplo, char *trans, int *n, int *k, float *alpha, + float *a, int *lda, float *b, int *ldb, float *beta, + float *c, int *ldc); + +int ssyrk_(char *uplo, char *trans, int *n, int *k, float *alpha, + float *a, int *lda, float *beta, float *c, int *ldc); + +int stbmv_(char *uplo, char *trans, char *diag, int *n, int *k, + float *a, int *lda, float *x, int *incx); + +int stbsv_(char *uplo, char *trans, char *diag, int *n, int *k, + float *a, int *lda, float *x, int *incx); + +int stpmv_(char *uplo, char *trans, char *diag, int *n, float *ap, + float *x, int *incx); + +int stpsv_(char *uplo, char *trans, char *diag, int *n, float *ap, + float *x, int *incx); + +int strmm_(char *side, char *uplo, char *transa, char *diag, int *m, + int *n, float *alpha, float *a, int *lda, float *b, + int *ldb); + +int strmv_(char *uplo, char *trans, char *diag, int *n, float *a, + int *lda, float *x, int *incx); + +int strsm_(char *side, char *uplo, char *transa, char *diag, int *m, + int *n, float *alpha, float *a, int *lda, float *b, + int *ldb); + +int strsv_(char *uplo, char *trans, char *diag, int *n, float *a, + int *lda, float *x, int *incx); + +int zaxpy_(int *n, dcomplex *ca, dcomplex *cx, int *incx, dcomplex *cy, + int *incy); + +int zcopy_(int *n, dcomplex *cx, int *incx, dcomplex *cy, int *incy); + +int zdscal_(int *n, double *sa, dcomplex *cx, int *incx); + +int zgbmv_(char *trans, int *m, int *n, int *kl, int *ku, + dcomplex *alpha, dcomplex *a, int *lda, dcomplex *x, int *incx, + dcomplex *beta, dcomplex *y, int *incy); + +int zgemm_(char *transa, char *transb, int *m, int *n, int *k, + dcomplex *alpha, dcomplex *a, int *lda, dcomplex *b, int *ldb, + dcomplex *beta, dcomplex *c, int *ldc); + +int zgemv_(char *trans, int *m, int *n, dcomplex *alpha, dcomplex *a, + int *lda, dcomplex *x, int *incx, dcomplex *beta, dcomplex *y, + int *incy); + +int zgerc_(int *m, int *n, dcomplex *alpha, dcomplex *x, int *incx, + dcomplex *y, int *incy, dcomplex *a, int *lda); + +int zgeru_(int *m, int *n, dcomplex *alpha, dcomplex *x, int *incx, + dcomplex *y, int *incy, dcomplex *a, int *lda); + +int zhbmv_(char *uplo, int *n, int *k, dcomplex *alpha, dcomplex *a, + int *lda, dcomplex *x, int *incx, dcomplex *beta, dcomplex *y, + int *incy); + +int zhemm_(char *side, char *uplo, int *m, int *n, dcomplex *alpha, + dcomplex *a, int *lda, dcomplex *b, int *ldb, dcomplex *beta, + dcomplex *c, int *ldc); + +int zhemv_(char *uplo, int *n, dcomplex *alpha, dcomplex *a, int *lda, + dcomplex *x, int *incx, dcomplex *beta, dcomplex *y, int *incy); + +int zher_(char *uplo, int *n, double *alpha, dcomplex *x, int *incx, + dcomplex *a, int *lda); + +int zher2_(char *uplo, int *n, dcomplex *alpha, dcomplex *x, int *incx, + dcomplex *y, int *incy, dcomplex *a, int *lda); + +int zher2k_(char *uplo, char *trans, int *n, int *k, dcomplex *alpha, + dcomplex *a, int *lda, dcomplex *b, int *ldb, double *beta, + dcomplex *c, int *ldc); + +int zherk_(char *uplo, char *trans, int *n, int *k, double *alpha, + dcomplex *a, int *lda, double *beta, dcomplex *c, int *ldc); + +int zhpmv_(char *uplo, int *n, dcomplex *alpha, dcomplex *ap, dcomplex *x, + int *incx, dcomplex *beta, dcomplex *y, int *incy); + +int zhpr_(char *uplo, int *n, double *alpha, dcomplex *x, int *incx, + dcomplex *ap); + +int zhpr2_(char *uplo, int *n, dcomplex *alpha, dcomplex *x, int *incx, + dcomplex *y, int *incy, dcomplex *ap); + +int zrotg_(dcomplex *ca, dcomplex *cb, double *c, dcomplex *s); + +int zscal_(int *n, dcomplex *ca, dcomplex *cx, int *incx); + +int zswap_(int *n, dcomplex *cx, int *incx, dcomplex *cy, int *incy); + +int zsymm_(char *side, char *uplo, int *m, int *n, dcomplex *alpha, + dcomplex *a, int *lda, dcomplex *b, int *ldb, dcomplex *beta, + dcomplex *c, int *ldc); + +int zsyr2k_(char *uplo, char *trans, int *n, int *k, dcomplex *alpha, + dcomplex *a, int *lda, dcomplex *b, int *ldb, dcomplex *beta, + dcomplex *c, int *ldc); + +int zsyrk_(char *uplo, char *trans, int *n, int *k, dcomplex *alpha, + dcomplex *a, int *lda, dcomplex *beta, dcomplex *c, int *ldc); + +int ztbmv_(char *uplo, char *trans, char *diag, int *n, int *k, + dcomplex *a, int *lda, dcomplex *x, int *incx); + +int ztbsv_(char *uplo, char *trans, char *diag, int *n, int *k, + dcomplex *a, int *lda, dcomplex *x, int *incx); + +int ztpmv_(char *uplo, char *trans, char *diag, int *n, dcomplex *ap, + dcomplex *x, int *incx); + +int ztpsv_(char *uplo, char *trans, char *diag, int *n, dcomplex *ap, + dcomplex *x, int *incx); + +int ztrmm_(char *side, char *uplo, char *transa, char *diag, int *m, + int *n, dcomplex *alpha, dcomplex *a, int *lda, dcomplex *b, + int *ldb); + +int ztrmv_(char *uplo, char *trans, char *diag, int *n, dcomplex *a, + int *lda, dcomplex *x, int *incx); + +int ztrsm_(char *side, char *uplo, char *transa, char *diag, int *m, + int *n, dcomplex *alpha, dcomplex *a, int *lda, dcomplex *b, + int *ldb); + +int ztrsv_(char *uplo, char *trans, char *diag, int *n, dcomplex *a, + int *lda, dcomplex *x, int *incx); diff --git a/liblinear/blas/daxpy.c b/liblinear/blas/daxpy.c new file mode 100644 index 0000000000..58f345a53a --- /dev/null +++ b/liblinear/blas/daxpy.c @@ -0,0 +1,49 @@ +#include "blas.h" + +int daxpy_(int *n, double *sa, double *sx, int *incx, double *sy, + int *incy) +{ + long int i, m, ix, iy, nn, iincx, iincy; + register double ssa; + + /* constant times a vector plus a vector. + uses unrolled loop for increments equal to one. + jack dongarra, linpack, 3/11/78. + modified 12/3/93, array(1) declarations changed to array(*) */ + + /* Dereference inputs */ + nn = *n; + ssa = *sa; + iincx = *incx; + iincy = *incy; + + if( nn > 0 && ssa != 0.0 ) + { + if (iincx == 1 && iincy == 1) /* code for both increments equal to 1 */ + { + m = nn-3; + for (i = 0; i < m; i += 4) + { + sy[i] += ssa * sx[i]; + sy[i+1] += ssa * sx[i+1]; + sy[i+2] += ssa * sx[i+2]; + sy[i+3] += ssa * sx[i+3]; + } + for ( ; i < nn; ++i) /* clean-up loop */ + sy[i] += ssa * sx[i]; + } + else /* code for unequal increments or equal increments not equal to 1 */ + { + ix = iincx >= 0 ? 0 : (1 - nn) * iincx; + iy = iincy >= 0 ? 0 : (1 - nn) * iincy; + for (i = 0; i < nn; i++) + { + sy[iy] += ssa * sx[ix]; + ix += iincx; + iy += iincy; + } + } + } + + return 0; +} /* daxpy_ */ diff --git a/liblinear/blas/ddot.c b/liblinear/blas/ddot.c new file mode 100644 index 0000000000..a64a2808f0 --- /dev/null +++ b/liblinear/blas/ddot.c @@ -0,0 +1,50 @@ +#include "blas.h" + +double ddot_(int *n, double *sx, int *incx, double *sy, int *incy) +{ + long int i, m, nn, iincx, iincy; + double stemp; + long int ix, iy; + + /* forms the dot product of two vectors. + uses unrolled loops for increments equal to one. + jack dongarra, linpack, 3/11/78. + modified 12/3/93, array(1) declarations changed to array(*) */ + + /* Dereference inputs */ + nn = *n; + iincx = *incx; + iincy = *incy; + + stemp = 0.0; + if (nn > 0) + { + if (iincx == 1 && iincy == 1) /* code for both increments equal to 1 */ + { + m = nn-4; + for (i = 0; i < m; i += 5) + stemp += sx[i] * sy[i] + sx[i+1] * sy[i+1] + sx[i+2] * sy[i+2] + + sx[i+3] * sy[i+3] + sx[i+4] * sy[i+4]; + + for ( ; i < nn; i++) /* clean-up loop */ + stemp += sx[i] * sy[i]; + } + else /* code for unequal increments or equal increments not equal to 1 */ + { + ix = 0; + iy = 0; + if (iincx < 0) + ix = (1 - nn) * iincx; + if (iincy < 0) + iy = (1 - nn) * iincy; + for (i = 0; i < nn; i++) + { + stemp += sx[ix] * sy[iy]; + ix += iincx; + iy += iincy; + } + } + } + + return stemp; +} /* ddot_ */ diff --git a/liblinear/blas/dnrm2.c b/liblinear/blas/dnrm2.c new file mode 100644 index 0000000000..e50cdf777d --- /dev/null +++ b/liblinear/blas/dnrm2.c @@ -0,0 +1,62 @@ +#include /* Needed for fabs() and sqrt() */ +#include "blas.h" + +double dnrm2_(int *n, double *x, int *incx) +{ + long int ix, nn, iincx; + double norm, scale, absxi, ssq, temp; + +/* DNRM2 returns the euclidean norm of a vector via the function + name, so that + + DNRM2 := sqrt( x'*x ) + + -- This version written on 25-October-1982. + Modified on 14-October-1993 to inline the call to SLASSQ. + Sven Hammarling, Nag Ltd. */ + + /* Dereference inputs */ + nn = *n; + iincx = *incx; + + if( nn > 0 && iincx > 0 ) + { + if (nn == 1) + { + norm = fabs(x[0]); + } + else + { + scale = 0.0; + ssq = 1.0; + + /* The following loop is equivalent to this call to the LAPACK + auxiliary routine: CALL SLASSQ( N, X, INCX, SCALE, SSQ ) */ + + for (ix=(nn-1)*iincx; ix>=0; ix-=iincx) + { + if (x[ix] != 0.0) + { + absxi = fabs(x[ix]); + if (scale < absxi) + { + temp = scale / absxi; + ssq = ssq * (temp * temp) + 1.0; + scale = absxi; + } + else + { + temp = absxi / scale; + ssq += temp * temp; + } + } + } + norm = scale * sqrt(ssq); + } + } + else + norm = 0.0; + + return norm; + +} /* dnrm2_ */ diff --git a/liblinear/blas/dscal.c b/liblinear/blas/dscal.c new file mode 100644 index 0000000000..a0eca0c399 --- /dev/null +++ b/liblinear/blas/dscal.c @@ -0,0 +1,44 @@ +#include "blas.h" + +int dscal_(int *n, double *sa, double *sx, int *incx) +{ + long int i, m, nincx, nn, iincx; + double ssa; + + /* scales a vector by a constant. + uses unrolled loops for increment equal to 1. + jack dongarra, linpack, 3/11/78. + modified 3/93 to return if incx .le. 0. + modified 12/3/93, array(1) declarations changed to array(*) */ + + /* Dereference inputs */ + nn = *n; + iincx = *incx; + ssa = *sa; + + if (nn > 0 && iincx > 0) + { + if (iincx == 1) /* code for increment equal to 1 */ + { + m = nn-4; + for (i = 0; i < m; i += 5) + { + sx[i] = ssa * sx[i]; + sx[i+1] = ssa * sx[i+1]; + sx[i+2] = ssa * sx[i+2]; + sx[i+3] = ssa * sx[i+3]; + sx[i+4] = ssa * sx[i+4]; + } + for ( ; i < nn; ++i) /* clean-up loop */ + sx[i] = ssa * sx[i]; + } + else /* code for increment not equal to 1 */ + { + nincx = nn * iincx; + for (i = 0; i < nincx; i += iincx) + sx[i] = ssa * sx[i]; + } + } + + return 0; +} /* dscal_ */ diff --git a/liblinear/liblinear.vcxproj b/liblinear/liblinear.vcxproj new file mode 100755 index 0000000000..854c8684b9 --- /dev/null +++ b/liblinear/liblinear.vcxproj @@ -0,0 +1,95 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + + + + + + + + + + + {A7BE3D76-F20C-40C5-8986-DE4028B3B57D} + Win32Proj + liblinear + + + + StaticLibrary + true + Unicode + + + StaticLibrary + false + true + Unicode + + + + + + + + + + + + + . + + + . + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + MultiThreadedDebug + + + Windows + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + MultiThreaded + + + Windows + true + true + true + + + + + + \ No newline at end of file diff --git a/liblinear/linear.cpp b/liblinear/linear.cpp new file mode 100644 index 0000000000..152370373b --- /dev/null +++ b/liblinear/linear.cpp @@ -0,0 +1,2382 @@ +#include +#include +#include +#include +#include +#include "linear.h" +#include "tron.h" +typedef signed char schar; +template static inline void swap(T& x, T& y) { T t=x; x=y; y=t; } +#ifndef min +template static inline T min(T x,T y) { return (x static inline T max(T x,T y) { return (x>y)?x:y; } +#endif +template static inline void clone(T*& dst, S* src, int n) +{ + dst = new T[n]; + memcpy((void *)dst,(void *)src,sizeof(T)*n); +} +#define Malloc(type,n) (type *)malloc((n)*sizeof(type)) +#define INF HUGE_VAL + +static void print_string_stdout(const char *s) +{ + fputs(s,stdout); + fflush(stdout); +} + +static void (*liblinear_print_string) (const char *) = &print_string_stdout; + +#if 1 +static void info(const char *fmt,...) +{ + char buf[BUFSIZ]; + va_list ap; + va_start(ap,fmt); + vsprintf(buf,fmt,ap); + va_end(ap); + (*liblinear_print_string)(buf); +} +#else +static void info(const char *fmt,...) {} +#endif + +class l2r_lr_fun : public function +{ +public: + l2r_lr_fun(const problem *prob, double Cp, double Cn); + ~l2r_lr_fun(); + + double fun(double *w); + void grad(double *w, double *g); + void Hv(double *s, double *Hs); + + int get_nr_variable(void); + +private: + void Xv(double *v, double *Xv); + void XTv(double *v, double *XTv); + + double *C; + double *z; + double *D; + const problem *prob; +}; + +l2r_lr_fun::l2r_lr_fun(const problem *prob, double Cp, double Cn) +{ + int i; + int l=prob->l; + int *y=prob->y; + + this->prob = prob; + + z = new double[l]; + D = new double[l]; + C = new double[l]; + + for (i=0; iy; + int l=prob->l; + int w_size=get_nr_variable(); + + Xv(w, z); + for(i=0;i= 0) + f += C[i]*log(1 + exp(-yz)); + else + f += C[i]*(-yz+log(1 + exp(yz))); + } + f = 2*f; + for(i=0;iy; + int l=prob->l; + int w_size=get_nr_variable(); + + for(i=0;in; +} + +void l2r_lr_fun::Hv(double *s, double *Hs) +{ + int i; + int l=prob->l; + int w_size=get_nr_variable(); + double *wa = new double[l]; + + Xv(s, wa); + for(i=0;il; + feature_node **x=prob->x; + + for(i=0;iindex!=-1) + { + Xv[i]+=v[s->index-1]*s->value; + s++; + } + } +} + +void l2r_lr_fun::XTv(double *v, double *XTv) +{ + int i; + int l=prob->l; + int w_size=get_nr_variable(); + feature_node **x=prob->x; + + for(i=0;iindex!=-1) + { + XTv[s->index-1]+=v[i]*s->value; + s++; + } + } +} + +class l2r_l2_svc_fun : public function +{ +public: + l2r_l2_svc_fun(const problem *prob, double Cp, double Cn); + ~l2r_l2_svc_fun(); + + double fun(double *w); + void grad(double *w, double *g); + void Hv(double *s, double *Hs); + + int get_nr_variable(void); + +private: + void Xv(double *v, double *Xv); + void subXv(double *v, double *Xv); + void subXTv(double *v, double *XTv); + + double *C; + double *z; + double *D; + int *I; + int sizeI; + const problem *prob; +}; + +l2r_l2_svc_fun::l2r_l2_svc_fun(const problem *prob, double Cp, double Cn) +{ + int i; + int l=prob->l; + int *y=prob->y; + + this->prob = prob; + + z = new double[l]; + D = new double[l]; + C = new double[l]; + I = new int[l]; + + for (i=0; iy; + int l=prob->l; + int w_size=get_nr_variable(); + + Xv(w, z); + for(i=0;i 0) + f += C[i]*d*d; + } + f = 2*f; + for(i=0;iy; + int l=prob->l; + int w_size=get_nr_variable(); + + sizeI = 0; + for (i=0;in; +} + +void l2r_l2_svc_fun::Hv(double *s, double *Hs) +{ + int i; + int l=prob->l; + int w_size=get_nr_variable(); + double *wa = new double[l]; + + subXv(s, wa); + for(i=0;il; + feature_node **x=prob->x; + + for(i=0;iindex!=-1) + { + Xv[i]+=v[s->index-1]*s->value; + s++; + } + } +} + +void l2r_l2_svc_fun::subXv(double *v, double *Xv) +{ + int i; + feature_node **x=prob->x; + + for(i=0;iindex!=-1) + { + Xv[i]+=v[s->index-1]*s->value; + s++; + } + } +} + +void l2r_l2_svc_fun::subXTv(double *v, double *XTv) +{ + int i; + int w_size=get_nr_variable(); + feature_node **x=prob->x; + + for(i=0;iindex!=-1) + { + XTv[s->index-1]+=v[i]*s->value; + s++; + } + } +} + +// A coordinate descent algorithm for +// multi-class support vector machines by Crammer and Singer +// +// min_{\alpha} 0.5 \sum_m ||w_m(\alpha)||^2 + \sum_i \sum_m e^m_i alpha^m_i +// s.t. \alpha^m_i <= C^m_i \forall m,i , \sum_m \alpha^m_i=0 \forall i +// +// where e^m_i = 0 if y_i = m, +// e^m_i = 1 if y_i != m, +// C^m_i = C if m = y_i, +// C^m_i = 0 if m != y_i, +// and w_m(\alpha) = \sum_i \alpha^m_i x_i +// +// Given: +// x, y, C +// eps is the stopping tolerance +// +// solution will be put in w +// +// See Appendix of LIBLINEAR paper, Fan et al. (2008) + +#define GETI(i) (prob->y[i]) +// To support weights for instances, use GETI(i) (i) + +class Solver_MCSVM_CS +{ + public: + Solver_MCSVM_CS(const problem *prob, int nr_class, double *C, double eps=0.1, int max_iter=100000); + ~Solver_MCSVM_CS(); + void Solve(double *w); + private: + void solve_sub_problem(double A_i, int yi, double C_yi, int active_i, double *alpha_new); + bool be_shrunk(int i, int m, int yi, double alpha_i, double minG); + double *B, *C, *G; + int w_size, l; + int nr_class; + int max_iter; + double eps; + const problem *prob; +}; + +Solver_MCSVM_CS::Solver_MCSVM_CS(const problem *prob, int nr_class, double *weighted_C, double eps, int max_iter) +{ + this->w_size = prob->n; + this->l = prob->l; + this->nr_class = nr_class; + this->eps = eps; + this->max_iter = max_iter; + this->prob = prob; + this->B = new double[nr_class]; + this->G = new double[nr_class]; + this->C = weighted_C; +} + +Solver_MCSVM_CS::~Solver_MCSVM_CS() +{ + delete[] B; + delete[] G; +} + +int compare_double(const void *a, const void *b) +{ + if(*(double *)a > *(double *)b) + return -1; + if(*(double *)a < *(double *)b) + return 1; + return 0; +} + +void Solver_MCSVM_CS::solve_sub_problem(double A_i, int yi, double C_yi, int active_i, double *alpha_new) +{ + int r; + double *D; + + clone(D, B, active_i); + if(yi < active_i) + D[yi] += A_i*C_yi; + qsort(D, active_i, sizeof(double), compare_double); + + double beta = D[0] - A_i*C_yi; + for(r=1;rx[i]; + QD[i] = 0; + while(xi->index != -1) + { + QD[i] += (xi->value)*(xi->value); + xi++; + } + active_size_i[i] = nr_class; + y_index[i] = prob->y[i]; + index[i] = i; + } + + while(iter < max_iter) + { + double stopping = -INF; + for(i=0;i 0) + { + for(m=0;mx[i]; + while(xi->index!= -1) + { + double *w_i = &w[(xi->index-1)*nr_class]; + for(m=0;mvalue); + xi++; + } + + double minG = INF; + double maxG = -INF; + for(m=0;m maxG) + maxG = G[m]; + } + if(y_index[i] < active_size_i[i]) + if(alpha_i[prob->y[i]] < C[GETI(i)] && G[y_index[i]] < minG) + minG = G[y_index[i]]; + + for(m=0;mm) + { + if(!be_shrunk(i, active_size_i[i], y_index[i], + alpha_i[alpha_index_i[active_size_i[i]]], minG)) + { + swap(alpha_index_i[m], alpha_index_i[active_size_i[i]]); + swap(G[m], G[active_size_i[i]]); + if(y_index[i] == active_size_i[i]) + y_index[i] = m; + else if(y_index[i] == m) + y_index[i] = active_size_i[i]; + break; + } + active_size_i[i]--; + } + } + } + + if(active_size_i[i] <= 1) + { + active_size--; + swap(index[s], index[active_size]); + s--; + continue; + } + + if(maxG-minG <= 1e-12) + continue; + else + stopping = max(maxG - minG, stopping); + + for(m=0;m= 1e-12) + { + d_ind[nz_d] = alpha_index_i[m]; + d_val[nz_d] = d; + nz_d++; + } + } + + xi = prob->x[i]; + while(xi->index != -1) + { + double *w_i = &w[(xi->index-1)*nr_class]; + for(m=0;mvalue; + xi++; + } + } + } + + iter++; + if(iter % 10 == 0) + { + info("."); + } + + if(stopping < eps_shrink) + { + if(stopping < eps && start_from_all == true) + break; + else + { + active_size = l; + for(i=0;i= max_iter) + info("\nWARNING: reaching max number of iterations\n"); + + // calculate objective value + double v = 0; + int nSV = 0; + for(i=0;i 0) + nSV++; + } + for(i=0;iy[i]]; + info("Objective value = %lf\n",v); + info("nSV = %d\n",nSV); + + delete [] alpha; + delete [] alpha_new; + delete [] index; + delete [] QD; + delete [] d_ind; + delete [] d_val; + delete [] alpha_index; + delete [] y_index; + delete [] active_size_i; +} + +// A coordinate descent algorithm for +// L1-loss and L2-loss SVM dual problems +// +// min_\alpha 0.5(\alpha^T (Q + D)\alpha) - e^T \alpha, +// s.t. 0 <= alpha_i <= upper_bound_i, +// +// where Qij = yi yj xi^T xj and +// D is a diagonal matrix +// +// In L1-SVM case: +// upper_bound_i = Cp if y_i = 1 +// upper_bound_i = Cn if y_i = -1 +// D_ii = 0 +// In L2-SVM case: +// upper_bound_i = INF +// D_ii = 1/(2*Cp) if y_i = 1 +// D_ii = 1/(2*Cn) if y_i = -1 +// +// Given: +// x, y, Cp, Cn +// eps is the stopping tolerance +// +// solution will be put in w +// +// See Algorithm 3 of Hsieh et al., ICML 2008 + +#undef GETI +#define GETI(i) (y[i]+1) +// To support weights for instances, use GETI(i) (i) + +static void solve_l2r_l1l2_svc( + const problem *prob, double *w, double eps, + double Cp, double Cn, int solver_type) +{ + int l = prob->l; + int w_size = prob->n; + int i, s, iter = 0; + double C, d, G; + double *QD = new double[l]; + int max_iter = 1000; + int *index = new int[l]; + double *alpha = new double[l]; + schar *y = new schar[l]; + int active_size = l; + + // PG: projected gradient, for shrinking and stopping + double PG; + double PGmax_old = INF; + double PGmin_old = -INF; + double PGmax_new, PGmin_new; + + // default solver_type: L2R_L2LOSS_SVC_DUAL + double diag[3] = {0.5/Cn, 0, 0.5/Cp}; + double upper_bound[3] = {INF, 0, INF}; + if(solver_type == L2R_L1LOSS_SVC_DUAL) + { + diag[0] = 0; + diag[2] = 0; + upper_bound[0] = Cn; + upper_bound[2] = Cp; + } + + for(i=0; iy[i] > 0) + { + y[i] = +1; + } + else + { + y[i] = -1; + } + QD[i] = diag[GETI(i)]; + + feature_node *xi = prob->x[i]; + while (xi->index != -1) + { + QD[i] += (xi->value)*(xi->value); + xi++; + } + index[i] = i; + } + + while (iter < max_iter) + { + PGmax_new = -INF; + PGmin_new = INF; + + for (i=0; ix[i]; + while(xi->index!= -1) + { + G += w[xi->index-1]*(xi->value); + xi++; + } + G = G*yi-1; + + C = upper_bound[GETI(i)]; + G += alpha[i]*diag[GETI(i)]; + + PG = 0; + if (alpha[i] == 0) + { + if (G > PGmax_old) + { + active_size--; + swap(index[s], index[active_size]); + s--; + continue; + } + else if (G < 0) + PG = G; + } + else if (alpha[i] == C) + { + if (G < PGmin_old) + { + active_size--; + swap(index[s], index[active_size]); + s--; + continue; + } + else if (G > 0) + PG = G; + } + else + PG = G; + + PGmax_new = max(PGmax_new, PG); + PGmin_new = min(PGmin_new, PG); + + if(fabs(PG) > 1.0e-12) + { + double alpha_old = alpha[i]; + alpha[i] = min(max(alpha[i] - G/QD[i], 0.0), C); + d = (alpha[i] - alpha_old)*yi; + xi = prob->x[i]; + while (xi->index != -1) + { + w[xi->index-1] += d*xi->value; + xi++; + } + } + } + + iter++; + if(iter % 10 == 0) + info("."); + + if(PGmax_new - PGmin_new <= eps) + { + if(active_size == l) + break; + else + { + active_size = l; + info("*"); + PGmax_old = INF; + PGmin_old = -INF; + continue; + } + } + PGmax_old = PGmax_new; + PGmin_old = PGmin_new; + if (PGmax_old <= 0) + PGmax_old = INF; + if (PGmin_old >= 0) + PGmin_old = -INF; + } + + info("\noptimization finished, #iter = %d\n",iter); + if (iter >= max_iter) + info("\nWARNING: reaching max number of iterations\nUsing -s 2 may be faster (also see FAQ)\n\n"); + + // calculate objective value + + double v = 0; + int nSV = 0; + for(i=0; i 0) + ++nSV; + } + info("Objective value = %lf\n",v/2); + info("nSV = %d\n",nSV); + + delete [] QD; + delete [] alpha; + delete [] y; + delete [] index; +} + +// A coordinate descent algorithm for +// the dual of L2-regularized logistic regression problems +// +// min_\alpha 0.5(\alpha^T Q \alpha) + \sum \alpha_i log (\alpha_i) + (upper_bound_i - alpha_i) log (upper_bound_i - alpha_i) , +// s.t. 0 <= alpha_i <= upper_bound_i, +// +// where Qij = yi yj xi^T xj and +// upper_bound_i = Cp if y_i = 1 +// upper_bound_i = Cn if y_i = -1 +// +// Given: +// x, y, Cp, Cn +// eps is the stopping tolerance +// +// solution will be put in w +// +// See Algorithm 5 of Yu et al., MLJ 2010 + +#undef GETI +#define GETI(i) (y[i]+1) +// To support weights for instances, use GETI(i) (i) + +void solve_l2r_lr_dual(const problem *prob, double *w, double eps, double Cp, double Cn) +{ + int l = prob->l; + int w_size = prob->n; + int i, s, iter = 0; + double *xTx = new double[l]; + int max_iter = 1000; + int *index = new int[l]; + double *alpha = new double[2*l]; // store alpha and C - alpha + schar *y = new schar[l]; + int max_inner_iter = 100; // for inner Newton + double innereps = 1e-2; + double innereps_min = min(1e-8, eps); + double upper_bound[3] = {Cn, 0, Cp}; + + for(i=0; iy[i] > 0) + { + y[i] = +1; + } + else + { + y[i] = -1; + } + alpha[2*i] = min(0.001*upper_bound[GETI(i)], 1e-8); + alpha[2*i+1] = upper_bound[GETI(i)] - alpha[2*i]; + + xTx[i] = 0; + feature_node *xi = prob->x[i]; + while (xi->index != -1) + { + xTx[i] += (xi->value)*(xi->value); + w[xi->index-1] += y[i]*alpha[2*i]*xi->value; + xi++; + } + index[i] = i; + } + + while (iter < max_iter) + { + for (i=0; ix[i]; + while (xi->index != -1) + { + ywTx += w[xi->index-1]*xi->value; + xi++; + } + ywTx *= y[i]; + double a = xisq, b = ywTx; + + // Decide to minimize g_1(z) or g_2(z) + int ind1 = 2*i, ind2 = 2*i+1, sign = 1; + if(0.5*a*(alpha[ind2]-alpha[ind1])+b < 0) + { + ind1 = 2*i+1; + ind2 = 2*i; + sign = -1; + } + + // g_t(z) = z*log(z) + (C-z)*log(C-z) + 0.5a(z-alpha_old)^2 + sign*b(z-alpha_old) + double alpha_old = alpha[ind1]; + double z = alpha_old; + if(C - z < 0.5 * C) + z = 0.1*z; + double gp = a*(z-alpha_old)+sign*b+log(z/(C-z)); + Gmax = max(Gmax, fabs(gp)); + + // Newton method on the sub-problem + const double eta = 0.1; // xi in the paper + int inner_iter = 0; + while (inner_iter <= max_inner_iter) + { + if(fabs(gp) < innereps) + break; + double gpp = a + C/(C-z)/z; + double tmpz = z - gp/gpp; + if(tmpz <= 0) + z *= eta; + else // tmpz in (0, C) + z = tmpz; + gp = a*(z-alpha_old)+sign*b+log(z/(C-z)); + newton_iter++; + inner_iter++; + } + + if(inner_iter > 0) // update w + { + alpha[ind1] = z; + alpha[ind2] = C-z; + xi = prob->x[i]; + while (xi->index != -1) + { + w[xi->index-1] += sign*(z-alpha_old)*yi*xi->value; + xi++; + } + } + } + + iter++; + if(iter % 10 == 0) + info("."); + + if(Gmax < eps) + break; + + if(newton_iter <= l/10) + innereps = max(innereps_min, 0.1*innereps); + + } + + info("\noptimization finished, #iter = %d\n",iter); + if (iter >= max_iter) + info("\nWARNING: reaching max number of iterations\nUsing -s 0 may be faster (also see FAQ)\n\n"); + + // calculate objective value + + double v = 0; + for(i=0; il; + int w_size = prob_col->n; + int j, s, iter = 0; + int max_iter = 1000; + int active_size = w_size; + int max_num_linesearch = 20; + + double sigma = 0.01; + double d, G_loss, G, H; + double Gmax_old = INF; + double Gmax_new, Gnorm1_new; + double Gnorm1_init; + double d_old, d_diff; + double loss_old, loss_new; + double appxcond, cond; + + int *index = new int[w_size]; + schar *y = new schar[l]; + double *b = new double[l]; // b = 1-ywTx + double *xj_sq = new double[w_size]; + feature_node *x; + + double C[3] = {Cn,0,Cp}; + + for(j=0; jy[j] > 0) + y[j] = 1; + else + y[j] = -1; + } + for(j=0; jx[j]; + while(x->index != -1) + { + int ind = x->index-1; + double val = x->value; + x->value *= y[ind]; // x->value stores yi*xij + xj_sq[j] += C[GETI(ind)]*val*val; + x++; + } + } + + while(iter < max_iter) + { + Gmax_new = 0; + Gnorm1_new = 0; + + for(j=0; jx[j]; + while(x->index != -1) + { + int ind = x->index-1; + if(b[ind] > 0) + { + double val = x->value; + double tmp = C[GETI(ind)]*val; + G_loss -= tmp*b[ind]; + H += tmp*val; + } + x++; + } + G_loss *= 2; + + G = G_loss; + H *= 2; + H = max(H, 1e-12); + + double Gp = G+1; + double Gn = G-1; + double violation = 0; + if(w[j] == 0) + { + if(Gp < 0) + violation = -Gp; + else if(Gn > 0) + violation = Gn; + else if(Gp>Gmax_old/l && Gn<-Gmax_old/l) + { + active_size--; + swap(index[s], index[active_size]); + s--; + continue; + } + } + else if(w[j] > 0) + violation = fabs(Gp); + else + violation = fabs(Gn); + + Gmax_new = max(Gmax_new, violation); + Gnorm1_new += violation; + + // obtain Newton direction d + if(Gp <= H*w[j]) + d = -Gp/H; + else if(Gn >= H*w[j]) + d = -Gn/H; + else + d = -w[j]; + + if(fabs(d) < 1.0e-12) + continue; + + double delta = fabs(w[j]+d)-fabs(w[j]) + G*d; + d_old = 0; + int num_linesearch; + for(num_linesearch=0; num_linesearch < max_num_linesearch; num_linesearch++) + { + d_diff = d_old - d; + cond = fabs(w[j]+d)-fabs(w[j]) - sigma*delta; + + appxcond = xj_sq[j]*d*d + G_loss*d + cond; + if(appxcond <= 0) + { + x = prob_col->x[j]; + while(x->index != -1) + { + b[x->index-1] += d_diff*x->value; + x++; + } + break; + } + + if(num_linesearch == 0) + { + loss_old = 0; + loss_new = 0; + x = prob_col->x[j]; + while(x->index != -1) + { + int ind = x->index-1; + if(b[ind] > 0) + loss_old += C[GETI(ind)]*b[ind]*b[ind]; + double b_new = b[ind] + d_diff*x->value; + b[ind] = b_new; + if(b_new > 0) + loss_new += C[GETI(ind)]*b_new*b_new; + x++; + } + } + else + { + loss_new = 0; + x = prob_col->x[j]; + while(x->index != -1) + { + int ind = x->index-1; + double b_new = b[ind] + d_diff*x->value; + b[ind] = b_new; + if(b_new > 0) + loss_new += C[GETI(ind)]*b_new*b_new; + x++; + } + } + + cond = cond + loss_new - loss_old; + if(cond <= 0) + break; + else + { + d_old = d; + d *= 0.5; + delta *= 0.5; + } + } + + w[j] += d; + + // recompute b[] if line search takes too many steps + if(num_linesearch >= max_num_linesearch) + { + info("#"); + for(int i=0; ix[i]; + while(x->index != -1) + { + b[x->index-1] -= w[i]*x->value; + x++; + } + } + } + } + + if(iter == 0) + Gnorm1_init = Gnorm1_new; + iter++; + if(iter % 10 == 0) + info("."); + + if(Gnorm1_new <= eps*Gnorm1_init) + { + if(active_size == w_size) + break; + else + { + active_size = w_size; + info("*"); + Gmax_old = INF; + continue; + } + } + + Gmax_old = Gmax_new; + } + + info("\noptimization finished, #iter = %d\n", iter); + if(iter >= max_iter) + info("\nWARNING: reaching max number of iterations\n"); + + // calculate objective value + + double v = 0; + int nnz = 0; + for(j=0; jx[j]; + while(x->index != -1) + { + x->value *= prob_col->y[x->index-1]; // restore x->value + x++; + } + if(w[j] != 0) + { + v += fabs(w[j]); + nnz++; + } + } + for(j=0; j 0) + v += C[GETI(j)]*b[j]*b[j]; + + info("Objective value = %lf\n", v); + info("#nonzeros/#features = %d/%d\n", nnz, w_size); + + delete [] index; + delete [] y; + delete [] b; + delete [] xj_sq; +} + +// A coordinate descent algorithm for +// L1-regularized logistic regression problems +// +// min_w \sum |wj| + C \sum log(1+exp(-yi w^T xi)), +// +// Given: +// x, y, Cp, Cn +// eps is the stopping tolerance +// +// solution will be put in w +// +// See Yuan et al. (2011) and appendix of LIBLINEAR paper, Fan et al. (2008) + +#undef GETI +#define GETI(i) (y[i]+1) +// To support weights for instances, use GETI(i) (i) + +static void solve_l1r_lr( + const problem *prob_col, double *w, double eps, + double Cp, double Cn) +{ + int l = prob_col->l; + int w_size = prob_col->n; + int j, s, newton_iter=0, iter=0; + int max_newton_iter = 100; + int max_iter = 1000; + int max_num_linesearch = 20; + int active_size; + int QP_active_size; + + double nu = 1e-12; + double inner_eps = 1; + double sigma = 0.01; + double w_norm=0, w_norm_new; + double z, G, H; + double Gnorm1_init; + double Gmax_old = INF; + double Gmax_new, Gnorm1_new; + double QP_Gmax_old = INF; + double QP_Gmax_new, QP_Gnorm1_new; + double delta, negsum_xTd, cond; + + int *index = new int[w_size]; + schar *y = new schar[l]; + double *Hdiag = new double[w_size]; + double *Grad = new double[w_size]; + double *wpd = new double[w_size]; + double *xjneg_sum = new double[w_size]; + double *xTd = new double[l]; + double *exp_wTx = new double[l]; + double *exp_wTx_new = new double[l]; + double *tau = new double[l]; + double *D = new double[l]; + feature_node *x; + + double C[3] = {Cn,0,Cp}; + + for(j=0; jy[j] > 0) + y[j] = 1; + else + y[j] = -1; + + // assume initial w is 0 + exp_wTx[j] = 1; + tau[j] = C[GETI(j)]*0.5; + D[j] = C[GETI(j)]*0.25; + } + for(j=0; jx[j]; + while(x->index != -1) + { + int ind = x->index-1; + if(y[ind] == -1) + xjneg_sum[j] += C[GETI(ind)]*x->value; + x++; + } + } + + while(newton_iter < max_newton_iter) + { + Gmax_new = 0; + Gnorm1_new = 0; + active_size = w_size; + + for(s=0; sx[j]; + while(x->index != -1) + { + int ind = x->index-1; + Hdiag[j] += x->value*x->value*D[ind]; + tmp += x->value*tau[ind]; + x++; + } + Grad[j] = -tmp + xjneg_sum[j]; + + double Gp = Grad[j]+1; + double Gn = Grad[j]-1; + double violation = 0; + if(w[j] == 0) + { + if(Gp < 0) + violation = -Gp; + else if(Gn > 0) + violation = Gn; + //outer-level shrinking + else if(Gp>Gmax_old/l && Gn<-Gmax_old/l) + { + active_size--; + swap(index[s], index[active_size]); + s--; + continue; + } + } + else if(w[j] > 0) + violation = fabs(Gp); + else + violation = fabs(Gn); + + Gmax_new = max(Gmax_new, violation); + Gnorm1_new += violation; + } + + if(newton_iter == 0) + Gnorm1_init = Gnorm1_new; + + if(Gnorm1_new <= eps*Gnorm1_init) + break; + + iter = 0; + QP_Gmax_old = INF; + QP_active_size = active_size; + + for(int i=0; ix[j]; + G = Grad[j] + (wpd[j]-w[j])*nu; + while(x->index != -1) + { + int ind = x->index-1; + G += x->value*D[ind]*xTd[ind]; + x++; + } + + double Gp = G+1; + double Gn = G-1; + double violation = 0; + if(wpd[j] == 0) + { + if(Gp < 0) + violation = -Gp; + else if(Gn > 0) + violation = Gn; + //inner-level shrinking + else if(Gp>QP_Gmax_old/l && Gn<-QP_Gmax_old/l) + { + QP_active_size--; + swap(index[s], index[QP_active_size]); + s--; + continue; + } + } + else if(wpd[j] > 0) + violation = fabs(Gp); + else + violation = fabs(Gn); + + QP_Gmax_new = max(QP_Gmax_new, violation); + QP_Gnorm1_new += violation; + + // obtain solution of one-variable problem + if(Gp <= H*wpd[j]) + z = -Gp/H; + else if(Gn >= H*wpd[j]) + z = -Gn/H; + else + z = -wpd[j]; + + if(fabs(z) < 1.0e-12) + continue; + z = min(max(z,-10.0),10.0); + + wpd[j] += z; + + x = prob_col->x[j]; + while(x->index != -1) + { + int ind = x->index-1; + xTd[ind] += x->value*z; + x++; + } + } + + iter++; + + if(QP_Gnorm1_new <= inner_eps*Gnorm1_init) + { + //inner stopping + if(QP_active_size == active_size) + break; + //active set reactivation + else + { + QP_active_size = active_size; + QP_Gmax_old = INF; + continue; + } + } + + QP_Gmax_old = QP_Gmax_new; + } + + if(iter >= max_iter) + info("WARNING: reaching max number of inner iterations\n"); + + delta = 0; + w_norm_new = 0; + for(j=0; j= max_num_linesearch) + { + for(int i=0; ix[i]; + while(x->index != -1) + { + exp_wTx[x->index-1] += w[i]*x->value; + x++; + } + } + + for(int i=0; i= max_newton_iter) + info("WARNING: reaching max number of iterations\n"); + + // calculate objective value + + double v = 0; + int nnz = 0; + for(j=0; jl; + int n = prob->n; + int nnz = 0; + int *col_ptr = new int[n+1]; + feature_node *x_space; + prob_col->l = l; + prob_col->n = n; + prob_col->y = new int[l]; + prob_col->x = new feature_node*[n]; + + for(i=0; iy[i] = prob->y[i]; + + for(i=0; ix[i]; + while(x->index != -1) + { + nnz++; + col_ptr[x->index]++; + x++; + } + } + for(i=1; ix[i] = &x_space[col_ptr[i]]; + + for(i=0; ix[i]; + while(x->index != -1) + { + int ind = x->index-1; + x_space[col_ptr[ind]].index = i+1; // starts from 1 + x_space[col_ptr[ind]].value = x->value; + col_ptr[ind]++; + x++; + } + } + for(i=0; il; + int max_nr_class = 16; + int nr_class = 0; + int *label = Malloc(int,max_nr_class); + int *count = Malloc(int,max_nr_class); + int *data_label = Malloc(int,l); + int i; + + for(i=0;iy[i]; + int j; + for(j=0;jeps; + int pos = 0; + int neg = 0; + for(int i=0;il;i++) + if(prob->y[i]==+1) + pos++; + neg = prob->l - pos; + + function *fun_obj=NULL; + switch(param->solver_type) + { + case L2R_LR: + { + fun_obj=new l2r_lr_fun(prob, Cp, Cn); + TRON tron_obj(fun_obj, eps*min(pos,neg)/prob->l); + tron_obj.set_print_string(liblinear_print_string); + tron_obj.tron(w); + delete fun_obj; + break; + } + case L2R_L2LOSS_SVC: + { + fun_obj=new l2r_l2_svc_fun(prob, Cp, Cn); + TRON tron_obj(fun_obj, eps*min(pos,neg)/prob->l); + tron_obj.set_print_string(liblinear_print_string); + tron_obj.tron(w); + delete fun_obj; + break; + } + case L2R_L2LOSS_SVC_DUAL: + solve_l2r_l1l2_svc(prob, w, eps, Cp, Cn, L2R_L2LOSS_SVC_DUAL); + break; + case L2R_L1LOSS_SVC_DUAL: + solve_l2r_l1l2_svc(prob, w, eps, Cp, Cn, L2R_L1LOSS_SVC_DUAL); + break; + case L1R_L2LOSS_SVC: + { + problem prob_col; + feature_node *x_space = NULL; + transpose(prob, &x_space ,&prob_col); + solve_l1r_l2_svc(&prob_col, w, eps*min(pos,neg)/prob->l, Cp, Cn); + delete [] prob_col.y; + delete [] prob_col.x; + delete [] x_space; + break; + } + case L1R_LR: + { + problem prob_col; + feature_node *x_space = NULL; + transpose(prob, &x_space ,&prob_col); + solve_l1r_lr(&prob_col, w, eps*min(pos,neg)/prob->l, Cp, Cn); + delete [] prob_col.y; + delete [] prob_col.x; + delete [] x_space; + break; + } + case L2R_LR_DUAL: + solve_l2r_lr_dual(prob, w, eps, Cp, Cn); + break; + default: + fprintf(stderr, "Error: unknown solver_type\n"); + break; + } +} + +// +// Interface functions +// +model* train(const problem *prob, const parameter *param) +{ + int i,j; + int l = prob->l; + int n = prob->n; + int w_size = prob->n; + model *model_ = Malloc(model,1); + + if(prob->bias>=0) + model_->nr_feature=n-1; + else + model_->nr_feature=n; + model_->param = *param; + model_->bias = prob->bias; + + int nr_class; + int *label = NULL; + int *start = NULL; + int *count = NULL; + int *perm = Malloc(int,l); + + // group training data of the same class + group_classes(prob,&nr_class,&label,&start,&count,perm); + + model_->nr_class=nr_class; + model_->label = Malloc(int,nr_class); + for(i=0;ilabel[i] = label[i]; + + // calculate weighted C + double *weighted_C = Malloc(double, nr_class); + for(i=0;iC; + for(i=0;inr_weight;i++) + { + for(j=0;jweight_label[i] == label[j]) + break; + if(j == nr_class) + fprintf(stderr,"WARNING: class label %d specified in weight is not found\n", param->weight_label[i]); + else + weighted_C[j] *= param->weight[i]; + } + + // constructing the subproblem + feature_node **x = Malloc(feature_node *,l); + for(i=0;ix[perm[i]]; + + int k; + problem sub_prob; + sub_prob.l = l; + sub_prob.n = n; + sub_prob.x = Malloc(feature_node *,sub_prob.l); + sub_prob.y = Malloc(int,sub_prob.l); + + for(k=0; ksolver_type == MCSVM_CS) + { + model_->w=Malloc(double, n*nr_class); + for(i=0;ieps); + Solver.Solve(model_->w); + } + else + { + if(nr_class == 2) + { + model_->w=Malloc(double, w_size); + + int e0 = start[0]+count[0]; + k=0; + for(; kw[0], weighted_C[0], weighted_C[1]); + } + else + { + model_->w=Malloc(double, w_size*nr_class); + double *w=Malloc(double, w_size); + for(i=0;iC); + + for(int j=0;jw[j*nr_class+i] = w[j]; + } + free(w); + } + + } + + free(x); + free(label); + free(start); + free(count); + free(perm); + free(sub_prob.x); + free(sub_prob.y); + free(weighted_C); + return model_; +} + +void cross_validation(const problem *prob, const parameter *param, int nr_fold, int *target) +{ + int i; + int *fold_start = Malloc(int,nr_fold+1); + int l = prob->l; + int *perm = Malloc(int,l); + + for(i=0;ibias; + subprob.n = prob->n; + subprob.l = l-(end-begin); + subprob.x = Malloc(struct feature_node*,subprob.l); + subprob.y = Malloc(int,subprob.l); + + k=0; + for(j=0;jx[perm[j]]; + subprob.y[k] = prob->y[perm[j]]; + ++k; + } + for(j=end;jx[perm[j]]; + subprob.y[k] = prob->y[perm[j]]; + ++k; + } + struct model *submodel = train(&subprob,param); + for(j=begin;jx[perm[j]]); + free_and_destroy_model(&submodel); + free(subprob.x); + free(subprob.y); + } + free(fold_start); + free(perm); +} + +int predict_values(const struct model *model_, const struct feature_node *x, double *dec_values) +{ + int idx; + int n; + if(model_->bias>=0) + n=model_->nr_feature+1; + else + n=model_->nr_feature; + double *w=model_->w; + int nr_class=model_->nr_class; + int i; + int nr_w; + if(nr_class==2 && model_->param.solver_type != MCSVM_CS) + nr_w = 1; + else + nr_w = nr_class; + + const feature_node *lx=x; + for(i=0;iindex)!=-1; lx++) + { + // the dimension of testing data may exceed that of training + if(idx<=n) + for(i=0;ivalue; + } + + if(nr_class==2) + return (dec_values[0]>0)?model_->label[0]:model_->label[1]; + else + { + int dec_max_idx = 0; + for(i=1;i dec_values[dec_max_idx]) + dec_max_idx = i; + } + return model_->label[dec_max_idx]; + } +} + +int predict(const model *model_, const feature_node *x) +{ + double *dec_values = Malloc(double, model_->nr_class); + int label=predict_values(model_, x, dec_values); + free(dec_values); + return label; +} + +int predict_probability(const struct model *model_, const struct feature_node *x, double* prob_estimates) +{ + if(check_probability_model(model_)) + { + int i; + int nr_class=model_->nr_class; + int nr_w; + if(nr_class==2) + nr_w = 1; + else + nr_w = nr_class; + + int label=predict_values(model_, x, prob_estimates); + for(i=0;inr_feature; + int n; + const parameter& param = model_->param; + + if(model_->bias>=0) + n=nr_feature+1; + else + n=nr_feature; + int w_size = n; + FILE *fp = fopen(model_file_name,"w"); + if(fp==NULL) return -1; + + int nr_w; + if(model_->nr_class==2 && model_->param.solver_type != MCSVM_CS) + nr_w=1; + else + nr_w=model_->nr_class; + + fprintf(fp, "solver_type %s\n", solver_type_table[param.solver_type]); + fprintf(fp, "nr_class %d\n", model_->nr_class); + fprintf(fp, "label"); + for(i=0; inr_class; i++) + fprintf(fp, " %d", model_->label[i]); + fprintf(fp, "\n"); + + fprintf(fp, "nr_feature %d\n", nr_feature); + + fprintf(fp, "bias %.16g\n", model_->bias); + + fprintf(fp, "w\n"); + for(i=0; iw[i*nr_w+j]); + fprintf(fp, "\n"); + } + + if (ferror(fp) != 0 || fclose(fp) != 0) return -1; + else return 0; +} + +struct model *load_model(const char *model_file_name) +{ + FILE *fp = fopen(model_file_name,"r"); + if(fp==NULL) return NULL; + + int i; + int nr_feature; + int n; + int nr_class; + double bias; + model *model_ = Malloc(model,1); + parameter& param = model_->param; + + model_->label = NULL; + + char cmd[81]; + while(1) + { + fscanf(fp,"%80s",cmd); + if(strcmp(cmd,"solver_type")==0) + { + fscanf(fp,"%80s",cmd); + int i; + for(i=0;solver_type_table[i];i++) + { + if(strcmp(solver_type_table[i],cmd)==0) + { + param.solver_type=i; + break; + } + } + if(solver_type_table[i] == NULL) + { + fprintf(stderr,"unknown solver type.\n"); + free(model_->label); + free(model_); + return NULL; + } + } + else if(strcmp(cmd,"nr_class")==0) + { + fscanf(fp,"%d",&nr_class); + model_->nr_class=nr_class; + } + else if(strcmp(cmd,"nr_feature")==0) + { + fscanf(fp,"%d",&nr_feature); + model_->nr_feature=nr_feature; + } + else if(strcmp(cmd,"bias")==0) + { + fscanf(fp,"%lf",&bias); + model_->bias=bias; + } + else if(strcmp(cmd,"w")==0) + { + break; + } + else if(strcmp(cmd,"label")==0) + { + int nr_class = model_->nr_class; + model_->label = Malloc(int,nr_class); + for(int i=0;ilabel[i]); + } + else + { + fprintf(stderr,"unknown text in model file: [%s]\n",cmd); + free(model_); + return NULL; + } + } + + nr_feature=model_->nr_feature; + if(model_->bias>=0) + n=nr_feature+1; + else + n=nr_feature; + int w_size = n; + int nr_w; + if(nr_class==2 && param.solver_type != MCSVM_CS) + nr_w = 1; + else + nr_w = nr_class; + + model_->w=Malloc(double, w_size*nr_w); + for(i=0; iw[i*nr_w+j]); + fscanf(fp, "\n"); + } + if (ferror(fp) != 0 || fclose(fp) != 0) return NULL; + + return model_; +} + +int get_nr_feature(const model *model_) +{ + return model_->nr_feature; +} + +int get_nr_class(const model *model_) +{ + return model_->nr_class; +} + +void get_labels(const model *model_, int* label) +{ + if (model_->label != NULL) + for(int i=0;inr_class;i++) + label[i] = model_->label[i]; +} + +void free_model_content(struct model *model_ptr) +{ + if(model_ptr->w != NULL) + free(model_ptr->w); + if(model_ptr->label != NULL) + free(model_ptr->label); +} + +void free_and_destroy_model(struct model **model_ptr_ptr) +{ + struct model *model_ptr = *model_ptr_ptr; + if(model_ptr != NULL) + { + free_model_content(model_ptr); + free(model_ptr); + } +} + +void destroy_param(parameter* param) +{ + if(param->weight_label != NULL) + free(param->weight_label); + if(param->weight != NULL) + free(param->weight); +} + +const char *check_parameter(const problem *prob, const parameter *param) +{ + if(param->eps <= 0) + return "eps <= 0"; + + if(param->C <= 0) + return "C <= 0"; + + if(param->solver_type != L2R_LR + && param->solver_type != L2R_L2LOSS_SVC_DUAL + && param->solver_type != L2R_L2LOSS_SVC + && param->solver_type != L2R_L1LOSS_SVC_DUAL + && param->solver_type != MCSVM_CS + && param->solver_type != L1R_L2LOSS_SVC + && param->solver_type != L1R_LR + && param->solver_type != L2R_LR_DUAL) + return "unknown solver type"; + + return NULL; +} + +int check_probability_model(const struct model *model_) +{ + return (model_->param.solver_type==L2R_LR || + model_->param.solver_type==L2R_LR_DUAL || + model_->param.solver_type==L1R_LR); +} + +void set_print_string_function(void (*print_func)(const char*)) +{ + if (print_func == NULL) + liblinear_print_string = &print_string_stdout; + else + liblinear_print_string = print_func; +} + diff --git a/liblinear/linear.def b/liblinear/linear.def new file mode 100644 index 0000000000..2425996ce6 --- /dev/null +++ b/liblinear/linear.def @@ -0,0 +1,18 @@ +LIBRARY liblinear +EXPORTS + train @1 + cross_validation @2 + save_model @3 + load_model @4 + get_nr_feature @5 + get_nr_class @6 + get_labels @7 + predict_values @8 + predict @9 + predict_probability @10 + free_and_destroy_model @11 + free_model_content @12 + destroy_param @13 + check_parameter @14 + check_probability_model @15 + set_print_string_function @16 diff --git a/liblinear/linear.h b/liblinear/linear.h new file mode 100644 index 0000000000..2a1aa28d2d --- /dev/null +++ b/liblinear/linear.h @@ -0,0 +1,73 @@ +#ifndef _LIBLINEAR_H +#define _LIBLINEAR_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct feature_node +{ + int index; + double value; +}; + +struct problem +{ + int l, n; + int *y; + struct feature_node **x; + double bias; /* < 0 if no bias term */ +}; + +enum { L2R_LR, L2R_L2LOSS_SVC_DUAL, L2R_L2LOSS_SVC, L2R_L1LOSS_SVC_DUAL, MCSVM_CS, L1R_L2LOSS_SVC, L1R_LR, L2R_LR_DUAL }; /* solver_type */ + +struct parameter +{ + int solver_type; + + /* these are for training only */ + double eps; /* stopping criteria */ + double C; + int nr_weight; + int *weight_label; + double* weight; +}; + +struct model +{ + struct parameter param; + int nr_class; /* number of classes */ + int nr_feature; + double *w; + int *label; /* label of each class */ + double bias; +}; + +struct model* train(const struct problem *prob, const struct parameter *param); +void cross_validation(const struct problem *prob, const struct parameter *param, int nr_fold, int *target); + +int predict_values(const struct model *model_, const struct feature_node *x, double* dec_values); +int predict(const struct model *model_, const struct feature_node *x); +int predict_probability(const struct model *model_, const struct feature_node *x, double* prob_estimates); + +int save_model(const char *model_file_name, const struct model *model_); +struct model *load_model(const char *model_file_name); + +int get_nr_feature(const struct model *model_); +int get_nr_class(const struct model *model_); +void get_labels(const struct model *model_, int* label); + +void free_model_content(struct model *model_ptr); +void free_and_destroy_model(struct model **model_ptr_ptr); +void destroy_param(struct parameter *param); + +const char *check_parameter(const struct problem *prob, const struct parameter *param); +int check_probability_model(const struct model *model); +void set_print_string_function(void (*print_func) (const char*)); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBLINEAR_H */ + diff --git a/liblinear/predict.c b/liblinear/predict.c new file mode 100644 index 0000000000..0b4be975b0 --- /dev/null +++ b/liblinear/predict.c @@ -0,0 +1,218 @@ +#include +#include +#include +#include +#include +#include "linear.h" + +struct feature_node *x; +int max_nr_attr = 64; + +struct model* model_; +int flag_predict_probability=0; + +void exit_input_error(int line_num) +{ + fprintf(stderr,"Wrong input format at line %d\n", line_num); + exit(1); +} + +static char *line = NULL; +static int max_line_len; + +static char* readline(FILE *input) +{ + int len; + + if(fgets(line,max_line_len,input) == NULL) + return NULL; + + while(strrchr(line,'\n') == NULL) + { + max_line_len *= 2; + line = (char *) realloc(line,max_line_len); + len = (int) strlen(line); + if(fgets(line+len,max_line_len-len,input) == NULL) + break; + } + return line; +} + +void do_predict(FILE *input, FILE *output, struct model* model_) +{ + int correct = 0; + int total = 0; + + int nr_class=get_nr_class(model_); + double *prob_estimates=NULL; + int j, n; + int nr_feature=get_nr_feature(model_); + if(model_->bias>=0) + n=nr_feature+1; + else + n=nr_feature; + + if(flag_predict_probability) + { + int *labels; + + if(!check_probability_model(model_)) + { + fprintf(stderr, "probability output is only supported for logistic regression\n"); + exit(1); + } + + labels=(int *) malloc(nr_class*sizeof(int)); + get_labels(model_,labels); + prob_estimates = (double *) malloc(nr_class*sizeof(double)); + fprintf(output,"labels"); + for(j=0;j=max_nr_attr-2) // need one more for index = -1 + { + max_nr_attr *= 2; + x = (struct feature_node *) realloc(x,max_nr_attr*sizeof(struct feature_node)); + } + + idx = strtok(NULL,":"); + val = strtok(NULL," \t"); + + if(val == NULL) + break; + errno = 0; + x[i].index = (int) strtol(idx,&endptr,10); + if(endptr == idx || errno != 0 || *endptr != '\0' || x[i].index <= inst_max_index) + exit_input_error(total+1); + else + inst_max_index = x[i].index; + + errno = 0; + x[i].value = strtod(val,&endptr); + if(endptr == val || errno != 0 || (*endptr != '\0' && !isspace(*endptr))) + exit_input_error(total+1); + + // feature indices larger than those in training are not used + if(x[i].index <= nr_feature) + ++i; + } + + if(model_->bias>=0) + { + x[i].index = n; + x[i].value = model_->bias; + i++; + } + x[i].index = -1; + + if(flag_predict_probability) + { + int j; + predict_label = predict_probability(model_,x,prob_estimates); + fprintf(output,"%d",predict_label); + for(j=0;jnr_class;j++) + fprintf(output," %g",prob_estimates[j]); + fprintf(output,"\n"); + } + else + { + predict_label = predict(model_,x); + fprintf(output,"%d\n",predict_label); + } + + if(predict_label == target_label) + ++correct; + ++total; + } + printf("Accuracy = %g%% (%d/%d)\n",(double) correct/total*100,correct,total); + if(flag_predict_probability) + free(prob_estimates); +} + +void exit_with_help() +{ + printf( + "Usage: predict [options] test_file model_file output_file\n" + "options:\n" + "-b probability_estimates: whether to output probability estimates, 0 or 1 (default 0)\n" + ); + exit(1); +} + +int main(int argc, char **argv) +{ + FILE *input, *output; + int i; + + // parse options + for(i=1;i=argc) + exit_with_help(); + + input = fopen(argv[i],"r"); + if(input == NULL) + { + fprintf(stderr,"can't open input file %s\n",argv[i]); + exit(1); + } + + output = fopen(argv[i+2],"w"); + if(output == NULL) + { + fprintf(stderr,"can't open output file %s\n",argv[i+2]); + exit(1); + } + + if((model_=load_model(argv[i+1]))==0) + { + fprintf(stderr,"can't open model file %s\n",argv[i+1]); + exit(1); + } + + x = (struct feature_node *) malloc(max_nr_attr*sizeof(struct feature_node)); + do_predict(input, output, model_); + free_and_destroy_model(&model_); + free(line); + free(x); + fclose(input); + fclose(output); + return 0; +} + diff --git a/liblinear/train.c b/liblinear/train.c new file mode 100644 index 0000000000..4920313a08 --- /dev/null +++ b/liblinear/train.c @@ -0,0 +1,340 @@ +#include +#include +#include +#include +#include +#include +#include "linear.h" +#define Malloc(type,n) (type *)malloc((n)*sizeof(type)) +#define INF HUGE_VAL + +void print_null(const char *s) {} + +void exit_with_help() +{ + printf( + "Usage: train [options] training_set_file [model_file]\n" + "options:\n" + "-s type : set type of solver (default 1)\n" + " 0 -- L2-regularized logistic regression (primal)\n" + " 1 -- L2-regularized L2-loss support vector classification (dual)\n" + " 2 -- L2-regularized L2-loss support vector classification (primal)\n" + " 3 -- L2-regularized L1-loss support vector classification (dual)\n" + " 4 -- multi-class support vector classification by Crammer and Singer\n" + " 5 -- L1-regularized L2-loss support vector classification\n" + " 6 -- L1-regularized logistic regression\n" + " 7 -- L2-regularized logistic regression (dual)\n" + "-c cost : set the parameter C (default 1)\n" + "-e epsilon : set tolerance of termination criterion\n" + " -s 0 and 2\n" + " |f'(w)|_2 <= eps*min(pos,neg)/l*|f'(w0)|_2,\n" + " where f is the primal function and pos/neg are # of\n" + " positive/negative data (default 0.01)\n" + " -s 1, 3, 4 and 7\n" + " Dual maximal violation <= eps; similar to libsvm (default 0.1)\n" + " -s 5 and 6\n" + " |f'(w)|_1 <= eps*min(pos,neg)/l*|f'(w0)|_1,\n" + " where f is the primal function (default 0.01)\n" + "-B bias : if bias >= 0, instance x becomes [x; bias]; if < 0, no bias term added (default -1)\n" + "-wi weight: weights adjust the parameter C of different classes (see README for details)\n" + "-v n: n-fold cross validation mode\n" + "-q : quiet mode (no outputs)\n" + ); + exit(1); +} + +void exit_input_error(int line_num) +{ + fprintf(stderr,"Wrong input format at line %d\n", line_num); + exit(1); +} + +static char *line = NULL; +static int max_line_len; + +static char* readline(FILE *input) +{ + int len; + + if(fgets(line,max_line_len,input) == NULL) + return NULL; + + while(strrchr(line,'\n') == NULL) + { + max_line_len *= 2; + line = (char *) realloc(line,max_line_len); + len = (int) strlen(line); + if(fgets(line+len,max_line_len-len,input) == NULL) + break; + } + return line; +} + +void parse_command_line(int argc, char **argv, char *input_file_name, char *model_file_name); +void read_problem(const char *filename); +void do_cross_validation(); + +struct feature_node *x_space; +struct parameter param; +struct problem prob; +struct model* model_; +int flag_cross_validation; +int nr_fold; +double bias; + +int main(int argc, char **argv) +{ + char input_file_name[1024]; + char model_file_name[1024]; + const char *error_msg; + + parse_command_line(argc, argv, input_file_name, model_file_name); + read_problem(input_file_name); + error_msg = check_parameter(&prob,¶m); + + if(error_msg) + { + fprintf(stderr,"Error: %s\n",error_msg); + exit(1); + } + + if(flag_cross_validation) + { + do_cross_validation(); + } + else + { + model_=train(&prob, ¶m); + if(save_model(model_file_name, model_)) + { + fprintf(stderr,"can't save model to file %s\n",model_file_name); + exit(1); + } + free_and_destroy_model(&model_); + } + destroy_param(¶m); + free(prob.y); + free(prob.x); + free(x_space); + free(line); + + return 0; +} + +void do_cross_validation() +{ + int i; + int total_correct = 0; + int *target = Malloc(int, prob.l); + + cross_validation(&prob,¶m,nr_fold,target); + + for(i=0;i=argc) + exit_with_help(); + switch(argv[i-1][1]) + { + case 's': + param.solver_type = atoi(argv[i]); + break; + + case 'c': + param.C = atof(argv[i]); + break; + + case 'e': + param.eps = atof(argv[i]); + break; + + case 'B': + bias = atof(argv[i]); + break; + + case 'w': + ++param.nr_weight; + param.weight_label = (int *) realloc(param.weight_label,sizeof(int)*param.nr_weight); + param.weight = (double *) realloc(param.weight,sizeof(double)*param.nr_weight); + param.weight_label[param.nr_weight-1] = atoi(&argv[i-1][2]); + param.weight[param.nr_weight-1] = atof(argv[i]); + break; + + case 'v': + flag_cross_validation = 1; + nr_fold = atoi(argv[i]); + if(nr_fold < 2) + { + fprintf(stderr,"n-fold cross validation: n must >= 2\n"); + exit_with_help(); + } + break; + + case 'q': + print_func = &print_null; + i--; + break; + + default: + fprintf(stderr,"unknown option: -%c\n", argv[i-1][1]); + exit_with_help(); + break; + } + } + + set_print_string_function(print_func); + + // determine filenames + if(i>=argc) + exit_with_help(); + + strcpy(input_file_name, argv[i]); + + if(i max_index) + max_index = inst_max_index; + + if(prob.bias >= 0) + x_space[j++].value = prob.bias; + + x_space[j++].index = -1; + } + + if(prob.bias >= 0) + { + prob.n=max_index+1; + for(i=1;iindex = prob.n; + x_space[j-2].index = prob.n; + } + else + prob.n=max_index; + + fclose(fp); +} diff --git a/liblinear/tron.cpp b/liblinear/tron.cpp new file mode 100644 index 0000000000..bff50787e9 --- /dev/null +++ b/liblinear/tron.cpp @@ -0,0 +1,235 @@ +#include +#include +#include +#include +#include "tron.h" + +#ifndef min +template static inline T min(T x,T y) { return (x static inline T max(T x,T y) { return (x>y)?x:y; } +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +extern double dnrm2_(int *, double *, int *); +extern double ddot_(int *, double *, int *, double *, int *); +extern int daxpy_(int *, double *, double *, int *, double *, int *); +extern int dscal_(int *, double *, double *, int *); + +#ifdef __cplusplus +} +#endif + +static void default_print(const char *buf) +{ + fputs(buf,stdout); + fflush(stdout); +} + +void TRON::info(const char *fmt,...) +{ + char buf[BUFSIZ]; + va_list ap; + va_start(ap,fmt); + vsprintf(buf,fmt,ap); + va_end(ap); + (*tron_print_string)(buf); +} + +TRON::TRON(const function *fun_obj, double eps, int max_iter) +{ + this->fun_obj=const_cast(fun_obj); + this->eps=eps; + this->max_iter=max_iter; + tron_print_string = default_print; +} + +TRON::~TRON() +{ +} + +void TRON::tron(double *w) +{ + // Parameters for updating the iterates. + double eta0 = 1e-4, eta1 = 0.25, eta2 = 0.75; + + // Parameters for updating the trust region size delta. + double sigma1 = 0.25, sigma2 = 0.5, sigma3 = 4; + + int n = fun_obj->get_nr_variable(); + int i, cg_iter; + double delta, snorm, one=1.0; + double alpha, f, fnew, prered, actred, gs; + int search = 1, iter = 1, inc = 1; + double *s = new double[n]; + double *r = new double[n]; + double *w_new = new double[n]; + double *g = new double[n]; + + for (i=0; ifun(w); + fun_obj->grad(w, g); + delta = dnrm2_(&n, g, &inc); + double gnorm1 = delta; + double gnorm = gnorm1; + + if (gnorm <= eps*gnorm1) + search = 0; + + iter = 1; + + while (iter <= max_iter && search) + { + cg_iter = trcg(delta, g, s, r); + + memcpy(w_new, w, sizeof(double)*n); + daxpy_(&n, &one, s, &inc, w_new, &inc); + + gs = ddot_(&n, g, &inc, s, &inc); + prered = -0.5*(gs-ddot_(&n, s, &inc, r, &inc)); + fnew = fun_obj->fun(w_new); + + // Compute the actual reduction. + actred = f - fnew; + + // On the first iteration, adjust the initial step bound. + snorm = dnrm2_(&n, s, &inc); + if (iter == 1) + delta = min(delta, snorm); + + // Compute prediction alpha*snorm of the step. + if (fnew - f - gs <= 0) + alpha = sigma3; + else + alpha = max(sigma1, -0.5*(gs/(fnew - f - gs))); + + // Update the trust region bound according to the ratio of actual to predicted reduction. + if (actred < eta0*prered) + delta = min(max(alpha, sigma1)*snorm, sigma2*delta); + else if (actred < eta1*prered) + delta = max(sigma1*delta, min(alpha*snorm, sigma2*delta)); + else if (actred < eta2*prered) + delta = max(sigma1*delta, min(alpha*snorm, sigma3*delta)); + else + delta = max(delta, min(alpha*snorm, sigma3*delta)); + + info("iter %2d act %5.3e pre %5.3e delta %5.3e f %5.3e |g| %5.3e CG %3d\n", iter, actred, prered, delta, f, gnorm, cg_iter); + + if (actred > eta0*prered) + { + iter++; + memcpy(w, w_new, sizeof(double)*n); + f = fnew; + fun_obj->grad(w, g); + + gnorm = dnrm2_(&n, g, &inc); + if (gnorm <= eps*gnorm1) + break; + } + if (f < -1.0e+32) + { + info("warning: f < -1.0e+32\n"); + break; + } + if (fabs(actred) <= 0 && prered <= 0) + { + info("warning: actred and prered <= 0\n"); + break; + } + if (fabs(actred) <= 1.0e-12*fabs(f) && + fabs(prered) <= 1.0e-12*fabs(f)) + { + info("warning: actred and prered too small\n"); + break; + } + } + + delete[] g; + delete[] r; + delete[] w_new; + delete[] s; +} + +int TRON::trcg(double delta, double *g, double *s, double *r) +{ + int i, inc = 1; + int n = fun_obj->get_nr_variable(); + double one = 1; + double *d = new double[n]; + double *Hd = new double[n]; + double rTr, rnewTrnew, alpha, beta, cgtol; + + for (i=0; iHv(d, Hd); + + alpha = rTr/ddot_(&n, d, &inc, Hd, &inc); + daxpy_(&n, &alpha, d, &inc, s, &inc); + if (dnrm2_(&n, s, &inc) > delta) + { + info("cg reaches trust region boundary\n"); + alpha = -alpha; + daxpy_(&n, &alpha, d, &inc, s, &inc); + + double std = ddot_(&n, s, &inc, d, &inc); + double sts = ddot_(&n, s, &inc, s, &inc); + double dtd = ddot_(&n, d, &inc, d, &inc); + double dsq = delta*delta; + double rad = sqrt(std*std + dtd*(dsq-sts)); + if (std >= 0) + alpha = (dsq - sts)/(std + rad); + else + alpha = (rad - std)/dtd; + daxpy_(&n, &alpha, d, &inc, s, &inc); + alpha = -alpha; + daxpy_(&n, &alpha, Hd, &inc, r, &inc); + break; + } + alpha = -alpha; + daxpy_(&n, &alpha, Hd, &inc, r, &inc); + rnewTrnew = ddot_(&n, r, &inc, r, &inc); + beta = rnewTrnew/rTr; + dscal_(&n, &beta, d, &inc); + daxpy_(&n, &one, r, &inc, d, &inc); + rTr = rnewTrnew; + } + + delete[] d; + delete[] Hd; + + return(cg_iter); +} + +double TRON::norm_inf(int n, double *x) +{ + double dmax = fabs(x[0]); + for (int i=1; i= dmax) + dmax = fabs(x[i]); + return(dmax); +} + +void TRON::set_print_string(void (*print_string) (const char *buf)) +{ + tron_print_string = print_string; +} diff --git a/liblinear/tron.h b/liblinear/tron.h new file mode 100644 index 0000000000..3045c2e83a --- /dev/null +++ b/liblinear/tron.h @@ -0,0 +1,34 @@ +#ifndef _TRON_H +#define _TRON_H + +class function +{ +public: + virtual double fun(double *w) = 0 ; + virtual void grad(double *w, double *g) = 0 ; + virtual void Hv(double *s, double *Hs) = 0 ; + + virtual int get_nr_variable(void) = 0 ; + virtual ~function(void){} +}; + +class TRON +{ +public: + TRON(const function *fun_obj, double eps = 0.1, int max_iter = 1000); + ~TRON(); + + void tron(double *w); + void set_print_string(void (*i_print) (const char *buf)); + +private: + int trcg(double delta, double *g, double *s, double *r); + double norm_inf(int n, double *x); + + double eps; + int max_iter; + function *fun_obj; + void info(const char *fmt,...); + void (*tron_print_string)(const char *buf); +}; +#endif diff --git a/libnetutil/ARPHeader.cc b/libnetutil/ARPHeader.cc new file mode 100644 index 0000000000..72d7e8dac3 --- /dev/null +++ b/libnetutil/ARPHeader.cc @@ -0,0 +1,344 @@ + +/*************************************************************************** + * ARPHeader.cc -- The ARPHeader Class represents an ARP packet. It * + * contains methods to set any header field. In general, these methods do * + * error checkings and byte order conversion. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#include "ARPHeader.h" + +/******************************************************************************/ +/* CONTRUCTORS, DESTRUCTORS AND INITIALIZATION METHODS */ +/******************************************************************************/ +ARPHeader::ARPHeader() { + this->reset(); +} /* End of ARPHeader constructor */ + + +ARPHeader::~ARPHeader() { + +} /* End of ARPHeader destructor */ + + +/** Sets every attribute to its default value */ +void ARPHeader::reset(){ + memset (&this->h, 0, sizeof(nping_arp_hdr_t)); + this->length=ARP_HEADER_LEN; +} /* End of reset() */ + + +/******************************************************************************/ +/* PacketElement:: OVERWRITTEN METHODS */ +/******************************************************************************/ + +/** @warning This method is essential for the superclass getBinaryBuffer() + * method to work. Do NOT change a thing unless you know what you're doing */ +u8 *ARPHeader::getBufferPointer(){ + return (u8*)(&h); +} /* End of getBufferPointer() */ + + +/** Stores supplied packet in the internal buffer so the information + * can be accessed using the standard get & set methods. + * @warning The ARPHeader class is able to hold a maximum of 28 bytes. + * If the supplied buffer is longer than that, only the first 28 bytes will be + * stored in the internal buffer. + * @warning Supplied len MUST be at least 28 bytes (ARP header length). + * @return OP_SUCCESS on success and OP_FAILURE in case of error */ +int ARPHeader::storeRecvData(const u8 *buf, size_t len){ + if(buf==NULL || lenreset(); /* Re-init the object, just in case the caller had used it already */ + this->length=ARP_HEADER_LEN; + memcpy(&(this->h), buf, ARP_HEADER_LEN); + } + return OP_SUCCESS; +} /* End of storeRecvData() */ + + +/* Returns a protocol identifier. This is used by packet parsing funtions + * that return linked lists of PacketElement objects, to determine the protocol + * the object represents. */ +int ARPHeader::protocol_id() const { + return HEADER_TYPE_ARP; +} /* End of protocol_id() */ + + +/** Determines if the data stored in the object after an storeRecvData() call + * is valid and safe to use. This mainly checks the length of the data but may + * also test the value of certain protocol fields to ensure their correctness. + * @return the length, in bytes, of the header, if its found to be valid or + * OP_FAILURE (-1) otherwise. */ +int ARPHeader::validate(){ + if( this->length!=ARP_HEADER_LEN) + return OP_FAILURE; + else + return ARP_HEADER_LEN; +} /* End of validate() */ + + +/** Prints the contents of the header and calls print() on the next protocol + * header in the chain (if there is any). + * @return OP_SUCCESS on success and OP_FAILURE in case of error. */ +int ARPHeader::print(FILE *output, int detail) const { + fprintf(output, "ARP[]"); + if(this->next!=NULL){ + print_separator(output, detail); + next->print(output, detail); + } + return OP_SUCCESS; +} /* End of print() */ + + +/******************************************************************************/ +/* PROTOCOL-SPECIFIC METHODS */ +/******************************************************************************/ + +/** Sets HardwareType. + * @return OP_SUCCESS on success and OP_FAILURE in case of error. */ +int ARPHeader::setHardwareType(u16 val){ + this->h.ar_hrd=htons(val); + return OP_SUCCESS; +} /* End of setHardwareType() */ + + +/** Sets HardwareType to ETHERNET. + * @return OP_SUCCESS on success and OP_FAILURE in case of error. */ +int ARPHeader::setHardwareType(){ + this->h.ar_hrd=htons(HDR_ETH10MB); + return OP_SUCCESS; +} /* End of setHardwareType() */ + + +/** Returns value of attribute h.ar_hrd */ +u16 ARPHeader::getHardwareType(){ + return ntohs(this->h.ar_hrd); +} /* End of getHardwareType() */ + + +/** Sets ProtocolType. + * @return OP_SUCCESS on success and OP_FAILURE in case of error. */ +int ARPHeader::setProtocolType(u16 val){ + this->h.ar_pro=htons(val); + return OP_SUCCESS; +} /* End of setProtocolType() */ + + +/** Sets ProtocolType. + * @return OP_SUCCESS on success and OP_FAILURE in case of error. */ +int ARPHeader::setProtocolType(){ + this->h.ar_pro=htons(0x0800); /* DEFAULT: IPv4 */ + return OP_SUCCESS; +} /* End of setProtocolType() */ + + +/** Returns value of attribute h.ar_pro */ +u16 ARPHeader::getProtocolType(){ + return ntohs(this->h.ar_pro); +} /* End of getProtocolType() */ + + +/** Sets HwAddrLen. + * @return OP_SUCCESS on success and OP_FAILURE in case of error. */ +int ARPHeader::setHwAddrLen(u8 val){ + this->h.ar_hln=val; + return OP_SUCCESS; +} /* End of setHwAddrLen() */ + + +/** Sets HwAddrLen. + * @return OP_SUCCESS on success and OP_FAILURE in case of error. */ +int ARPHeader::setHwAddrLen(){ + this->h.ar_hln=ETH_ADDRESS_LEN; + return OP_SUCCESS; +} /* End of setHwAddrLen() */ + + +/** Returns value of attribute h.ar_hln */ +u8 ARPHeader::getHwAddrLen(){ + return this->h.ar_hln; +} /* End of getHwAddrLen() */ + + +/** Sets ProtoAddrLen. + * @return OP_SUCCESS on success and OP_FAILURE in case of error. */ +int ARPHeader::setProtoAddrLen(u8 val){ + this->h.ar_pln=val; + return OP_SUCCESS; +} /* End of setProtoAddrLen() */ + + +/** Sets ProtoAddrLen. + * @return OP_SUCCESS on success and OP_FAILURE in case of error. */ +int ARPHeader::setProtoAddrLen(){ + this->h.ar_pln=IPv4_ADDRESS_LEN; /* DEFAULT: IPv4 */ + return OP_SUCCESS; +} /* End of setProtoAddrLen() */ + + +/** Returns value of attribute h.ar_pln */ +u8 ARPHeader::getProtoAddrLen(){ + return this->h.ar_pln; +} /* End of getProtoAddrLen() */ + + +/** Sets OpCode. + * @return OP_SUCCESS on success and OP_FAILURE in case of error. */ +int ARPHeader::setOpCode(u16 val){ + this->h.ar_op=htons(val); + return OP_SUCCESS; +} /* End of setOpCode() */ + + +/** Returns value of attribute h.ar_op */ +u16 ARPHeader::getOpCode(){ + return ntohs(this->h.ar_op); +} /* End of getOpCode() */ + + +/** Sets SenderMAC. + * @return OP_SUCCESS on success and OP_FAILURE in case of error. */ +int ARPHeader::setSenderMAC(const u8 * val){ + if(val==NULL) + return OP_FAILURE; + memcpy(this->h.data, val, ETH_ADDRESS_LEN); + return OP_SUCCESS; +} /* End of setSenderMAC() */ + + +/** Returns value of attribute h.ar_sha */ +u8 * ARPHeader::getSenderMAC(){ + return this->h.data; +} /* End of getSenderMAC() */ + + +/** Sets SenderIP. + * @return OP_SUCCESS on success and OP_FAILURE in case of error. */ +int ARPHeader::setSenderIP(struct in_addr val){ + memcpy(this->h.data+6, &val.s_addr, 4); + return OP_SUCCESS; +} /* End of setSenderIP() */ + + +/** Returns value of attribute h.ar_sip */ +u32 ARPHeader::getSenderIP(){ + u32 *p = (u32 *)(this->h.data+6); + return *p; +} /* End of getSenderIP() */ + + +/** Sets TargetMAC. + * @return OP_SUCCESS on success and OP_FAILURE in case of error. */ +int ARPHeader::setTargetMAC(u8 * val){ + if(val==NULL) + return OP_FAILURE; + memcpy(this->h.data+10, val, ETH_ADDRESS_LEN); + return OP_SUCCESS; +} /* End of setTargetMAC() */ + + +/** Returns value of attribute h.ar_tha */ +u8 * ARPHeader::getTargetMAC(){ + return this->h.data+10; +} /* End of getTargetMAC() */ + + +/** Sets TargetIP. + * @return OP_SUCCESS on success and OP_FAILURE in case of error. */ +int ARPHeader::setTargetIP(struct in_addr val){ + memcpy(this->h.data+16, &val.s_addr, 4); + return OP_SUCCESS; +} /* End of setTargetIP() */ + + +/** Returns value of attribute h.ar_tip */ +u32 ARPHeader::getTargetIP(){ + u32 *p = (u32 *)(this->h.data+16); + return *p; +} /* End of getTargetIP() */ diff --git a/libnetutil/ARPHeader.h b/libnetutil/ARPHeader.h new file mode 100644 index 0000000000..73ab069068 --- /dev/null +++ b/libnetutil/ARPHeader.h @@ -0,0 +1,251 @@ + +/*************************************************************************** + * ARPHeader.h -- The ARPHeader Class represents an ARP packet. It * + * contains methods to set any header field. In general, these methods do * + * error checkings and byte order conversion. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#ifndef __ARPHEADER_H__ +#define __ARPHEADER_H__ 1 + +#include "NetworkLayerElement.h" + +/* Lengths */ +#define ARP_HEADER_LEN 28 +#define IPv4_ADDRESS_LEN 4 +#define ETH_ADDRESS_LEN 6 + +/* Hardware Types */ +#define HDR_RESERVED 0 /* [RFC5494] */ +#define HDR_ETH10MB 1 /* Ethernet (10Mb) */ +#define HDR_ETH3MB 2 /* Experimental Ethernet (3Mb) */ +#define HDR_AX25 3 /* Amateur Radio AX.25 */ +#define HDR_PRONET_TR 4 /* Proteon ProNET Token Ring */ +#define HDR_CHAOS 5 /* Chaos */ +#define HDR_IEEE802 6 /* IEEE 802 Networks */ +#define HDR_ARCNET 7 /* ARCNET [RFC1201] */ +#define HDR_HYPERCHANNEL 8 /* Hyperchannel */ +#define HDR_LANSTAR 9 /* Lanstar */ +#define HDR_AUTONET 10 /* Autonet Short Address */ +#define HDR_LOCALTALK 11 /* LocalTalk */ +#define HDR_LOCALNET 12 /* LocalNet (IBM PCNet or SYTEK LocalNET) */ +#define HDR_ULTRALINK 13 /* Ultra link */ +#define HDR_SMDS 14 /* SMDS */ +#define HDR_FRAMERELAY 15 /* Frame Relay */ +#define HDR_ATM 16 /* Asynchronous Transmission Mode (ATM) */ +#define HDR_HDLC 17 /* HDLC */ +#define HDR_FIBRE 18 /* Fibre Channel [RFC4338] */ +#define HDR_ATMb 19 /* Asynchronous Transmission Mode (ATM) */ +#define HDR_SERIAL 20 /* Serial Line */ +#define HDR_ATMc 21 /* Asynchronous Transmission Mode [RFC2225] */ +#define HDR_MILSTD 22 /* MIL-STD-188-220 */ +#define HDR_METRICOM 23 /* Metricom */ +#define HDR_IEEE1394 24 /* IEEE 1394.199 */ +#define HDR_MAPOS 25 /* MAPOS [RFC2176] */ +#define HDR_TWINAXIAL 26 /* Twinaxial */ +#define HDR_EUI64 27 /* EUI-64 */ +#define HDR_HIPARP 28 /* HIPARP */ +#define HDR_ISO7816 29 /* IP and ARP over ISO 7816-3 */ +#define HDR_ARPSEC 30 /* ARPSec */ +#define HDR_IPSEC 31 /* IPsec tunnel */ +#define HDR_INFINIBAND 32 /* InfiniBand (TM) */ +#define HDR_TIA102 33 /* TIA-102 Project 25 Common Air Interface */ +#define HDR_WIEGAND 34 /* Wiegand Interface */ +#define HDR_PUREIP 35 /* Pure IP */ +#define HDR_HW_EXP1 36 /* HW_EXP1 [RFC5494] */ +#define HDR_HW_EXP2 37 /* HW_EXP2 [RFC5494] */ + +/* Operation Codes */ +#define OP_ARP_REQUEST 1 /* ARP Request */ +#define OP_ARP_REPLY 2 /* ARP Reply */ +#define OP_RARP_REQUEST 3 /* Reverse ARP Request */ +#define OP_RARP_REPLY 4 /* Reverse ARP Reply */ +#define OP_DRARP_REQUEST 5 /* DRARP-Request */ +#define OP_DRARP_REPLY 6 /* DRARP-Reply */ +#define OP_DRARP_ERROR 7 /* DRARP-Error */ +#define OP_INARP_REQUEST 8 /* InARP-Request */ +#define OP_INARP_REPLY 9 /* InARP-Reply */ +#define OP_ARPNAK 10 /* ARP-NAK */ +#define OP_MARS_REQUEST 11 /* MARS-Request */ +#define OP_MARS_MULTI 12 /* MARS-Multi */ +#define OP_MARS_MSERV 13 /* MARS-MServ */ +#define OP_MARS_JOIN 14 /* MARS-Join */ +#define OP_MARS_LEAVE 15 /* MARS-Leave */ +#define OP_MARS_NAK 16 /* MARS-NAK */ +#define OP_MARS_UNSERV 17 /* MARS-Unserv */ +#define OP_MARS_SJOIN 18 /* MARS-SJoin */ +#define OP_MARS_SLEAVE 19 /* MARS-SLeave */ +#define OP_MARS_GL_REQ 20 /* MARS-Grouplist-Request */ +#define OP_MARS_GL_REP 21 /* MARS-Grouplist-Reply */ +#define OP_MARS_REDIR_MAP 22 /* MARS-Redirect-Map */ +#define OP_MAPOS_UNARP 23 /* MAPOS-UNARP [RFC2176] */ +#define OP_EXP1 24 /* OP_EXP1 [RFC5494] */ +#define OP_EXP2 25 /* OP_EXP2 [RFC5494] */ +#define OP_RESERVED 65535 /* Reserved [RFC5494] */ + + +class ARPHeader : public NetworkLayerElement { + + private: + + struct nping_arp_hdr{ + + u16 ar_hrd; /* Hardware Type. */ + u16 ar_pro; /* Protocol Type. */ + u8 ar_hln; /* Hardware Address Length. */ + u8 ar_pln; /* Protocol Address Length. */ + u16 ar_op; /* Operation Code. */ + u8 data[20]; + // Cannot use these because the fucking alignment screws up + // everything. I miss ANSI C. + //u8 ar_sha[6]; /* Sender Hardware Address. */ + //u32 ar_sip; /* Sender Protocol Address (IPv4 address). */ + //u8 ar_tha[6]; /* Target Hardware Address. */ + //u32 ar_tip; /* Target Protocol Address (IPv4 address). */ + }__attribute__((__packed__)); + + typedef struct nping_arp_hdr nping_arp_hdr_t; + + nping_arp_hdr_t h; + + public: + + /* Misc */ + ARPHeader(); + ~ARPHeader(); + void reset(); + u8 *getBufferPointer(); + int storeRecvData(const u8 *buf, size_t len); + int protocol_id() const; + int validate(); + int print(FILE *output, int detail) const; + + /* Hardware Type */ + int setHardwareType(u16 t); + int setHardwareType(); + u16 getHardwareType(); + + /* Protocol Type */ + int setProtocolType(u16 t); + int setProtocolType(); + u16 getProtocolType(); + + /* Hardware Address Length */ + int setHwAddrLen(u8 v); + int setHwAddrLen(); + u8 getHwAddrLen(); + + /* Hardware Address Length */ + int setProtoAddrLen(u8 v); + int setProtoAddrLen(); + u8 getProtoAddrLen(); + + /* Operation Code */ + int setOpCode(u16 c); + u16 getOpCode(); + + /* Sender Hardware Address */ + int setSenderMAC(const u8 *m); + u8 *getSenderMAC(); + + /* Sender Protocol address */ + int setSenderIP(struct in_addr i); + u32 getSenderIP(); + + /* Target Hardware Address */ + int setTargetMAC(u8 *m); + u8 *getTargetMAC(); + + /* Target Protocol Address */ + int setTargetIP(struct in_addr i); + u32 getTargetIP(); + +}; /* End of class ARPHeader */ + +#endif /* __ARPHEADER_H__ */ + diff --git a/libnetutil/ApplicationLayerElement.h b/libnetutil/ApplicationLayerElement.h new file mode 100644 index 0000000000..e2d10be826 --- /dev/null +++ b/libnetutil/ApplicationLayerElement.h @@ -0,0 +1,102 @@ + +/*************************************************************************** + * ApplicationLayerElement.h -- Class ApplicationLayerElement is a * + * generic class that represents an application layer protocol header or * + * any kind of payload or buffer. Classes like RawData inherit from it. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#ifndef APPLICATIONLAYERELEMENT_H +#define APPLICATIONLAYERELEMENT_H 1 + +#include "PacketElement.h" + + +class ApplicationLayerElement : public PacketElement { +}; + +#endif diff --git a/libnetutil/DataLinkLayerElement.h b/libnetutil/DataLinkLayerElement.h new file mode 100755 index 0000000000..598bef703e --- /dev/null +++ b/libnetutil/DataLinkLayerElement.h @@ -0,0 +1,101 @@ + +/*************************************************************************** + * DataLinkLayerElement.h -- Class DataLinkLayerElement is a generic * + * class that represents a data link layer protocol header (and maybe a * + * footer) Classes like EthernetHeader inherit from it. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#ifndef DATALINKLAYERELEMENT_H +#define DATALINKLAYERELEMENT_H 1 + +#include "PacketElement.h" + +class DataLinkLayerElement : public PacketElement { +}; + +#endif diff --git a/libnetutil/DestOptsHeader.cc b/libnetutil/DestOptsHeader.cc new file mode 100644 index 0000000000..01f0e7e7db --- /dev/null +++ b/libnetutil/DestOptsHeader.cc @@ -0,0 +1,126 @@ + +/*************************************************************************** + * DestOptsHeader.cc -- The DestOptsHeader Class represents an IPv6 * + * Destination Options extension header. * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#include "DestOptsHeader.h" +#include + +/******************************************************************************/ +/* CONTRUCTORS, DESTRUCTORS AND INITIALIZATION METHODS */ +/******************************************************************************/ +DestOptsHeader::DestOptsHeader() { + this->reset(); +} /* End of DestOptsHeader constructor */ + + +DestOptsHeader::~DestOptsHeader() { + +} /* End of DestOptsHeader destructor */ + + +/** Prints the contents of the header and calls print() on the next protocol + * header in the chain (if there is any). + * @return OP_SUCCESS on success and OP_FAILURE in case of error. */ +int DestOptsHeader::print(FILE *output, int detail) const { + fprintf(output, "DestOpts[%d,%d]", this->h.nh, this->h.len); + // TODO: @todo : Implement this + if(this->next!=NULL){ + print_separator(output, detail); + next->print(output, detail); + } + return OP_SUCCESS; +} /* End of print() */ + + +/* Returns a protocol identifier. This is used by packet parsing funtions + * that return linked lists of PacketElement objects, to determine the protocol + * the object represents. */ +int DestOptsHeader::protocol_id() const { + return HEADER_TYPE_IPv6_OPTS; +} /* End of protocol_id() */ diff --git a/libnetutil/DestOptsHeader.h b/libnetutil/DestOptsHeader.h new file mode 100644 index 0000000000..f157b1e07f --- /dev/null +++ b/libnetutil/DestOptsHeader.h @@ -0,0 +1,117 @@ + +/*************************************************************************** + * DestOptsHeader.h -- The DestOptsHeader Class represents an IPv6 * + * Destination Options extension header. * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#ifndef __DESTOPTS_HEADER_H__ +#define __DESTOPTS_HEADER_H__ 1 + +#include "HopByHopHeader.h" + +class DestOptsHeader : public HopByHopHeader { + + private: + /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Next Header | Hdr Ext Len | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + | | + . . + . Options . + . . + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + // Implemented in HopByHopHeader.h + public: + DestOptsHeader(); + ~DestOptsHeader(); + int print(FILE *output, int detail) const; + int protocol_id() const; + +}; /* End of class DestOptsHeader */ + +#endif diff --git a/libnetutil/EthernetHeader.cc b/libnetutil/EthernetHeader.cc new file mode 100755 index 0000000000..a205970cc8 --- /dev/null +++ b/libnetutil/EthernetHeader.cc @@ -0,0 +1,250 @@ + +/*************************************************************************** + * EthernetHeader.cc -- The EthernetHeader Class represents an Ethernet * + * header and footer. It contains methods to set the different header * + * fields. These methods tipically perform the necessary error checks and * + * byte order conversions. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#include "EthernetHeader.h" + +/******************************************************************************/ +/* CONTRUCTORS, DESTRUCTORS AND INITIALIZATION METHODS */ +/******************************************************************************/ +EthernetHeader::EthernetHeader(){ + this->reset(); +} /* End of EthernetHeader constructor */ + + +EthernetHeader::~EthernetHeader(){ + +} /* End of EthernetHeader destructor */ + + +/** Sets every attribute to its default value */ +void EthernetHeader::reset(){ + memset(&this->h, 0, sizeof(nping_eth_hdr_t)); + this->length=ETH_HEADER_LEN; +} /* End of reset() */ + + +/** @warning This method is essential for the superclass getBinaryBuffer() + * method to work. Do NOT change a thing unless you know what you're doing */ +u8 * EthernetHeader::getBufferPointer(){ + return (u8*)(&h); +} /* End of getBufferPointer() */ + + +/******************************************************************************/ +/* PacketElement:: OVERWRITTEN METHODS */ +/******************************************************************************/ + +/** Stores supplied packet in the internal buffer so the information + * can be accessed using the standard get & set methods. + * @warning The EthernetHeader class is able to hold a maximum of 14 bytes. + * If the supplied buffer is longer than that, only the first 14 bytes will be + * stored in the internal buffer. + * @warning Supplied len MUST be at least 14 bytes (Ethernet header length). + * @return OP_SUCCESS on success and OP_FAILURE in case of error */ +int EthernetHeader::storeRecvData(const u8 *buf, size_t len){ + if(buf==NULL || lenreset(); /* Re-init the object, just in case the caller had used it already */ + this->length=ETH_HEADER_LEN; + memcpy(&(this->h), buf, ETH_HEADER_LEN); + } + return OP_SUCCESS; +} /* End of storeRecvData() */ + + +/* Returns a protocol identifier. This is used by packet parsing funtions + * that return linked lists of PacketElement objects, to determine the protocol + * the object represents. */ +int EthernetHeader::protocol_id() const { + return HEADER_TYPE_ETHERNET; +} /* End of protocol_id() */ + + +/** Determines if the data stored in the object after an storeRecvData() call + * is valid and safe to use. This mainly checks the length of the data but may + * also test the value of certain protocol fields to ensure their correctness. + * @return the length, in bytes, of the header, if its found to be valid or + * OP_FAILURE (-1) otherwise. */ +int EthernetHeader::validate(){ + if( this->length!=ETH_HEADER_LEN) + return OP_FAILURE; + else + return ETH_HEADER_LEN; +} /* End of validate() */ + + +/** Prints the contents of the header and calls print() on the next protocol + * header in the chain (if there is any). + * @return OP_SUCCESS on success and OP_FAILURE in case of error. */ +int EthernetHeader::print(FILE *output, int detail) const { + + fprintf(output, "Eth["); + + for(int i=0; i<6; i++){ + fprintf(output, "%02x", this->h.eth_smac[i]); + if(i<5) + fprintf(output, ":"); + } + + fprintf(output, " > "); + + for(int i=0; i<6; i++){ + fprintf(output, "%02x", this->h.eth_dmac[i]); + if(i<5) + fprintf(output, ":"); + } + + if(detail>=PRINT_DETAIL_MED) + fprintf(output, " Type=%04x", this->getEtherType()); + + fprintf(output, "]"); + + if(this->next!=NULL){ + print_separator(output, detail); + next->print(output, detail); + } + return OP_SUCCESS; +} /* End of print() */ + + +/******************************************************************************/ +/* PROTOCOL-SPECIFIC METHODS */ +/******************************************************************************/ + +/** Sets Source MAC address + * @warning Supplied buffer must contain at least 6 bytes */ +int EthernetHeader::setSrcMAC(const u8 *m){ + if(m==NULL) + netutil_fatal("EthernetHeader::setSrcMAC(u8*): NULL value supplied "); + memcpy(h.eth_smac, m, 6); + return OP_SUCCESS; +} /* End of setSrcMAC() */ + + +/** Returns source port in HOST byte order + * @warning Returned pointer points directly to a Class internal buffer. If + * contents are changed, the instance of the class will be affected. */ +const u8* EthernetHeader::getSrcMAC() const { + return this->h.eth_smac; +} /* End of getSrcMAC() */ + + +/** Sets Destination MAC address + * @warning Supplied buffer must contain at least 6 bytes */ +int EthernetHeader::setDstMAC(u8 *m){ + if(m==NULL) + netutil_fatal("EthernetHeader::setDstMAC(u8 *): NULL value supplied "); + memcpy(h.eth_dmac, m, 6); + return OP_SUCCESS; +} /* End of setDstMAC() */ + + + +/** Returns destination port in HOST byte order */ +const u8 *EthernetHeader::getDstMAC() const { + return this->h.eth_dmac; +} /* End of getDstMAC() */ + + +int EthernetHeader::setEtherType(u16 val){ + h.eth_type=htons(val); + return OP_SUCCESS; +} /* End of setEtherType() */ + + +/** Returns destination port in HOST byte order */ +const u16 EthernetHeader::getEtherType() const { + return ntohs(this->h.eth_type); +} /* End of getEtherType() */ + diff --git a/libnetutil/EthernetHeader.h b/libnetutil/EthernetHeader.h new file mode 100755 index 0000000000..9ad7ce48b2 --- /dev/null +++ b/libnetutil/EthernetHeader.h @@ -0,0 +1,164 @@ + +/*************************************************************************** + * EthernetHeader.h -- The EthernetHeader Class represents an Ethernet * + * header and footer. It contains methods to set the different header * + * fields. These methods tipically perform the necessary error checks and * + * byte order conversions. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#ifndef ETHERNETHEADER_H +#define ETHERNETHEADER_H 1 + +#include "DataLinkLayerElement.h" + +/* Ether Types. (From RFC 5342 http://www.rfc-editor.org/rfc/rfc5342.txt) */ +#define ETHTYPE_IPV4 0x0800 /* Internet Protocol Version 4 */ +#define ETHTYPE_ARP 0x0806 /* Address Resolution Protocol */ +#define ETHTYPE_FRAMERELAY 0x0808 /* Frame Relay ARP */ +#define ETHTYPE_PPTP 0x880B /* Point-to-Point Tunneling Protocol */ +#define ETHTYPE_GSMP 0x880C /* General Switch Management Protocol */ +#define ETHTYPE_RARP 0x8035 /* Reverse Address Resolution Protocol */ +#define ETHTYPE_IPV6 0x86DD /* Internet Protocol Version 6 */ +#define ETHTYPE_MPLS 0x8847 /* MPLS */ +#define ETHTYPE_MPS_UAL 0x8848 /* MPLS with upstream-assigned label */ +#define ETHTYPE_MCAP 0x8861 /* Multicast Channel Allocation Protocol */ +#define ETHTYPE_PPPOE_D 0x8863 /* PPP over Ethernet Discovery Stage */ +#define ETHTYPE_PPOE_S 0x8864 /* PPP over Ethernet Session Stage */ +#define ETHTYPE_CTAG 0x8100 /* Customer VLAN Tag Type */ +#define ETHTYPE_EPON 0x8808 /* Ethernet Passive Optical Network */ +#define ETHTYPE_PBNAC 0x888E /* Port-based network access control */ +#define ETHTYPE_STAG 0x88A8 /* Service VLAN tag identifier */ +#define ETHTYPE_ETHEXP1 0x88B5 /* Local Experimental Ethertype */ +#define ETHTYPE_ETHEXP2 0x88B6 /* Local Experimental Ethertype */ +#define ETHTYPE_ETHOUI 0x88B7 /* OUI Extended Ethertype */ +#define ETHTYPE_PREAUTH 0x88C7 /* Pre-Authentication */ +#define ETHTYPE_LLDP 0x88CC /* Link Layer Discovery Protocol (LLDP) */ +#define ETHTYPE_MACSEC 0x88E5 /* Media Access Control Security */ +#define ETHTYPE_MVRP 0x88F5 /* Multiple VLAN Registration Protocol */ +#define ETHTYPE_MMRP 0x88F6 /* Multiple Multicast Registration Protocol */ +#define ETHTYPE_FRRR 0x890D /* Fast Roaming Remote Request */ + +#define ETH_HEADER_LEN 14 + +class EthernetHeader : public DataLinkLayerElement { + + private: + + struct nping_eth_hdr{ + u8 eth_dmac[6]; + u8 eth_smac[6]; + u16 eth_type; + }__attribute__((__packed__)); + + typedef struct nping_eth_hdr nping_eth_hdr_t; + + nping_eth_hdr_t h; + + public: + + EthernetHeader(); + ~EthernetHeader(); + void reset(); + u8 *getBufferPointer(); + int storeRecvData(const u8 *buf, size_t len); + int protocol_id() const; + int validate(); + int print(FILE *output, int detail) const; + + int setSrcMAC(const u8 *m); + const u8 *getSrcMAC() const; + + int setDstMAC(u8 *m); + const u8 *getDstMAC() const; + + int setEtherType(u16 val); + const u16 getEtherType() const; + +}; + +#endif diff --git a/libnetutil/FragmentHeader.cc b/libnetutil/FragmentHeader.cc new file mode 100644 index 0000000000..1a7c0aa9d8 --- /dev/null +++ b/libnetutil/FragmentHeader.cc @@ -0,0 +1,243 @@ + +/*************************************************************************** + * FragmentHeader.cc -- The FragmentHeader Class represents an IPv6 * + * Hop-by-Hop extension header. * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#include "FragmentHeader.h" +#include + +/******************************************************************************/ +/* CONTRUCTORS, DESTRUCTORS AND INITIALIZATION METHODS */ +/******************************************************************************/ +FragmentHeader::FragmentHeader() { + this->reset(); +} /* End of FragmentHeader constructor */ + + +FragmentHeader::~FragmentHeader() { + +} /* End of FragmentHeader destructor */ + + +/** Sets every attribute to its default value */ +void FragmentHeader::reset(){ + memset(&this->h, 0, sizeof(nping_ipv6_ext_fragment_hdr_t)); + this->length=8; +} /* End of reset() */ + + +/******************************************************************************/ +/* PacketElement:: OVERWRITTEN METHODS */ +/******************************************************************************/ + +/** @warning This method is essential for the superclass getBinaryBuffer() + * method to work. Do NOT change a thing unless you know what you're doing */ +u8 *FragmentHeader::getBufferPointer(){ + return (u8*)(&this->h); +} /* End of getBufferPointer() */ + + +/** Stores supplied packet in the internal buffer so the information + * can be accessed using the standard get & set methods. + * @warning The FragmentHeader class is able to hold a maximum of + * sizeof(nping_icmpv6_hdr_t) bytes. If the supplied buffer is longer than + * that, only the first 1508 bytes will be stored in the internal buffer. + * @warning Supplied len MUST be at least 8 bytes (min ICMPv6 header length). + * @return OP_SUCCESS on success and OP_FAILURE in case of error */ +int FragmentHeader::storeRecvData(const u8 *buf, size_t len){ + if(buf==NULL || lenlength=0; + return OP_FAILURE; + }else{ + int stored_len = MIN(FRAGMENT_HEADER_LEN, len); + this->reset(); /* Re-init the object, just in case the caller had used it already */ + this->length=stored_len; + memcpy(&(this->h), buf, stored_len); + } + return OP_SUCCESS; +} /* End of storeRecvData() */ + + +/* Returns a protocol identifier. This is used by packet parsing funtions + * that return linked lists of PacketElement objects, to determine the protocol + * the object represents. */ +int FragmentHeader::protocol_id() const { + return HEADER_TYPE_IPv6_FRAG; +} /* End of protocol_id() */ + + + +/** Determines if the data stored in the object after an storeRecvData() call + * is valid and safe to use. This mainly checks the length of the data but may + * also test the value of certain protocol fields to ensure their correctness. + * @return the length, in bytes, of the header, if its found to be valid or + * OP_FAILURE (-1) otherwise. */ +int FragmentHeader::validate(){ + /* Check the object's length makes sense*/ + if(this->length != FRAGMENT_HEADER_LEN){ + return OP_FAILURE; + } + /* There is not much to check for here, since header fields may take any + * value. We could certainly check the NextHeader value, but let's leave + * that for the class user. */ + return this->length; +} /* End of validate() */ + + +/** Prints the contents of the header and calls print() on the next protocol + * header in the chain (if there is any). + * @return OP_SUCCESS on success and OP_FAILURE in case of error. */ +int FragmentHeader::print(FILE *output, int detail) const { + fprintf(output, "Fragment[%d, %d]", this->h.nh, this->h.id); + // TODO: @todo : Implement this + if(this->next!=NULL){ + print_separator(output, detail); + next->print(output, detail); + } + return OP_SUCCESS; +} /* End of print() */ + + +/******************************************************************************/ +/* PROTOCOL-SPECIFIC METHODS */ +/******************************************************************************/ + +/** Set Next Header field */ +int FragmentHeader::setNextHeader(u8 val){ + this->h.nh = val; + return OP_SUCCESS; +} /* End of setNextHeader() */ + + +/** Returns next header id */ +u8 FragmentHeader::getNextHeader(){ + return this->h.nh; +} /* End of getNextHeader() */ + + +/** Set Offset field */ +int FragmentHeader::setOffset(u16 val){ + this->h.off_res_flag[0]=(u8)(val >> 8); + this->h.off_res_flag[1]=(u8)((this->h.off_res_flag[1] & 0x7) | (val & ~0x7)); + return OP_SUCCESS; +} /* End of setOffset() */ + + +/** Returns fragment offset */ +u16 FragmentHeader::getOffset(){ + return ((this->h.off_res_flag[0] << 8) + this->h.off_res_flag[1]) & 0xfff8; +} /* End of getOffset() */ + + +/* Sets the "More Fragments" flag. */ +int FragmentHeader::setM(bool m_flag){ + if(m_flag) + this->h.off_res_flag[1]= (u8)((this->h.off_res_flag[1] & ~0x01) | 0x01); + else + this->h.off_res_flag[1]= (u8)((this->h.off_res_flag[1] & ~0x1)); + return OP_SUCCESS; +} /* End of setM() */ + + +/* Returns true if the "More Fragments" flag is set; false otherwise. */ +bool FragmentHeader::getM(){ + return (this->h.off_res_flag[1] & 0x01); +} /* End of getM() */ + + +/** Set the fragment identifier */ +int FragmentHeader::setIdentification(u32 val){ + this->h.id=htonl(val); + return OP_SUCCESS; +} /* End of setIdentification() */ + + +/** Returns the fragment identifier*/ +u32 FragmentHeader::getIdentification(){ + return ntohl(this->h.id); +} /* End of getIdentification.() */ diff --git a/libnetutil/FragmentHeader.h b/libnetutil/FragmentHeader.h new file mode 100644 index 0000000000..07f58a0101 --- /dev/null +++ b/libnetutil/FragmentHeader.h @@ -0,0 +1,144 @@ + +/*************************************************************************** + * FragmentHeader.h -- The FragmentHeader Class represents an IPv6 * + * Hop-by-Hop extension header. * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#ifndef __FRAGMENT_HEADER_H__ +#define __FRAGMENT_HEADER_H__ 1 + +#include "IPv6ExtensionHeader.h" + +#define FRAGMENT_HEADER_LEN 8 + + +class FragmentHeader : public IPv6ExtensionHeader { + + private: + + /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Next Header | Reserved | Fragment Offset |Res|M| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Identification | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + struct nping_ipv6_ext_fragment_hdr{ + u8 nh; + u8 res1; + u8 off_res_flag[2]; + u32 id; + }__attribute__((__packed__)); + typedef struct nping_ipv6_ext_fragment_hdr nping_ipv6_ext_fragment_hdr_t; + + nping_ipv6_ext_fragment_hdr_t h; + + public: + FragmentHeader(); + ~FragmentHeader(); + void reset(); + u8 *getBufferPointer(); + int storeRecvData(const u8 *buf, size_t len); + int protocol_id() const; + int validate(); + int print(FILE *output, int detail) const; + + /* Protocol specific methods */ + int setNextHeader(u8 val); + u8 getNextHeader(); + + int setOffset(u16 val); + u16 getOffset(); + + int setM(bool m_flag); + bool getM(); + + int setIdentification(u32 val); + u32 getIdentification(); + + +}; /* End of class FragmentHeader */ + +#endif diff --git a/libnetutil/HopByHopHeader.cc b/libnetutil/HopByHopHeader.cc new file mode 100644 index 0000000000..59df77bb28 --- /dev/null +++ b/libnetutil/HopByHopHeader.cc @@ -0,0 +1,418 @@ + +/*************************************************************************** + * HopByHopHeader.cc -- The HopByHopHeader Class represents an IPv6 * + * Hop-by-Hop extension header. * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#include "HopByHopHeader.h" +#include + +/******************************************************************************/ +/* CONTRUCTORS, DESTRUCTORS AND INITIALIZATION METHODS */ +/******************************************************************************/ +HopByHopHeader::HopByHopHeader() { + this->reset(); +} /* End of HopByHopHeader constructor */ + + +HopByHopHeader::~HopByHopHeader() { + +} /* End of HopByHopHeader destructor */ + + +/** Sets every attribute to its default value */ +void HopByHopHeader::reset(){ + memset(&this->h, 0, sizeof(nping_ipv6_ext_hopbyhop_hdr_t)); + curr_option=(u8*)this->h.options; + this->length=2; + this->addOption(EXTOPT_PADN, 4, (const u8*)"\x00\x00\x00\x00"); +} /* End of reset() */ + + +/******************************************************************************/ +/* PacketElement:: OVERWRITTEN METHODS */ +/******************************************************************************/ + +/** @warning This method is essential for the superclass getBinaryBuffer() + * method to work. Do NOT change a thing unless you know what you're doing */ +u8 *HopByHopHeader::getBufferPointer(){ + return (u8*)(&this->h); +} /* End of getBufferPointer() */ + + +/** Stores supplied packet in the internal buffer so the information + * can be accessed using the standard get & set methods. + * @warning The HopByHopHeader class is able to hold a maximum of + * sizeof(nping_icmpv6_hdr_t) bytes. If the supplied buffer is longer than + * that, only the first 1508 bytes will be stored in the internal buffer. + * @warning Supplied len MUST be at least 8 bytes (min ICMPv6 header length). + * @return OP_SUCCESS on success and OP_FAILURE in case of error */ +int HopByHopHeader::storeRecvData(const u8 *buf, size_t len){ + if(buf==NULL || lenlength=0; + return OP_FAILURE; + }else{ + /* Store the first 4 bytes, so we can access the HdrExtLen field. */ + memcpy(&(this->h), buf, 4); + + /* Check that the HdrExtLen field makes sense: + * 1) Check that it carries as many octets as it claims + * 2) Check that we don't exceed our internal storage space. */ + if( ((unsigned int)(this->h.len+1))*8 > len || (this->h.len+1)*8 > HOPBYHOP_MAX_HEADER_LEN){ + this->length=0; + return OP_FAILURE; + }else{ + int mylen=(this->h.len+1)*8; + this->reset(); + this->length=mylen; + memcpy(&(this->h), buf, this->length); + return OP_SUCCESS; + } + } + return OP_FAILURE; +} /* End of storeRecvData() */ + + +/* Returns a protocol identifier. This is used by packet parsing funtions + * that return linked lists of PacketElement objects, to determine the protocol + * the object represents. */ +int HopByHopHeader::protocol_id() const { + return HEADER_TYPE_IPv6_HOPOPT; +} /* End of protocol_id() */ + + +/** Determines if the data stored in the object after an storeRecvData() call + * is valid and safe to use. This mainly checks the length of the data but may + * also test the value of certain protocol fields to ensure their correctness. + * @return the length, in bytes, of the header, if its found to be valid or + * OP_FAILURE (-1) otherwise. */ +int HopByHopHeader::validate(){ + nping_ipv6_ext_hopbyhop_opt_t *curr_opt=NULL; + u8 *curr_pnt=(u8 *)this->h.options; + int bytes_left=this->length-2; + + /* Check the object's length makes sense*/ + if(this->length%8!=0 || this->length < HOPBYHOP_MIN_HEADER_LEN || this->length > HOPBYHOP_MAX_HEADER_LEN){ + return OP_FAILURE; + } + /* Check the header's length field. It should match the object's length */ + if( (this->h.len+1)*8 != this->length){ + return OP_FAILURE; + } + + /* Now validate the TLV-encoded options. */ + while(bytes_left>0){ + /* Use the opts structure as a template to access current option */ + curr_opt=(nping_ipv6_ext_hopbyhop_opt_t *)curr_pnt; + + /* Let's see what we have. */ + switch(curr_opt->type){ + + /* Pad1 + +-+-+-+-+-+-+-+-+ + | 0 | + +-+-+-+-+-+-+-+-+ */ + case EXTOPT_PAD1: + curr_pnt++; /* Skip one octet */ + bytes_left++; + break; + + /* PadN + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - - - - - - - - + | 1 | Padding Len | Padding + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - - - - - - - - */ + case EXTOPT_PADN: + /* Check we have as many octets as the option advertises */ + if(bytes_left<2+curr_opt->len) + return OP_FAILURE; + curr_pnt+=2+curr_opt->len; + bytes_left-=2+curr_opt->len; + break; + + /* Jumbo Payload Option (RFC 2675). + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Option Type | Opt Data Len | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Jumbo Payload Length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + case EXTOPT_JUMBO: + /* Jumbo has a fixed length of 4 octets (plus 2). */ + if(curr_opt->len!=4) + return OP_FAILURE; + /* Check if we actually have all the octets */ + if(bytes_left<2+4) + return OP_FAILURE; + curr_pnt+=6; + bytes_left-=6; + break; + + /* Tunnel Encapsulation limit (RFC 2473). + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Option Type | 1 | Tun Encap Lim | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + case EXTOPT_TUNENCAPLIM: + /* This one also has a fixed length. */ + if(curr_opt->len!=1) + return OP_FAILURE; + /* Check if we actually have all the octets */ + if(bytes_left<2+1) + return OP_FAILURE; + curr_pnt+=3; + bytes_left-=3; + break; + + /* Router Alert (RFC 2711). + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Option Type | 2 | Value (2 octets) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + case EXTOPT_ROUTERALERT: + /* Fixed length (two octets)*/ + if(curr_opt->len!=2) + return OP_FAILURE; + /* Check that we actually have all the octets */ + if(bytes_left<2+2) + return OP_FAILURE; + curr_pnt+=4; + bytes_left-=4; + break; + + /* Quick-Start (RFC 4782). + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Option | Length=6 | Func. | Rate | Not Used | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | QS Nonce | R | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + case EXTOPT_QUICKSTART: + /* Fixed length (two octets)*/ + if(curr_opt->len!=6) + return OP_FAILURE; + /* Check that we actually have all the octets */ + if(bytes_left<2+6) + return OP_FAILURE; + curr_pnt+=8; + bytes_left-=8; + break; + + /* CALIPSO (RFC 5570). + +----------------------------+ + | Option Type | Option Length| + +-------------+---------------+-------------+--------------+ + | CALIPSO Domain of Interpretation | + +-------------+---------------+-------------+--------------+ + | Cmpt Length | Sens Level | Checksum (CRC-16) | + +-------------+---------------+-------------+--------------+ + | Compartment Bitmap (Optional; variable length) | + +-------------+---------------+-------------+--------------+ */ + case EXTOPT_CALIPSO: + /* The length of the CALIPSO option is variable because the + * Compartment Bitmap is not mandatory. However, the length + * must be at least 8. */ + if(curr_opt->len<8) + return OP_FAILURE; + /* Check that we actually have all the octets */ + if(bytes_left<2+curr_opt->len) + return OP_FAILURE; + curr_pnt+=2+curr_opt->len; + bytes_left-=2+curr_opt->len; + break; + + + /* Home Address (RFC 6275). + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Option Type | Option Length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + + + | | + + Home Address + + | | + + + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/ + case EXTOPT_HOMEADDR: + /* Fixed length of 16 */ + if(curr_opt->len!=16) + return OP_FAILURE; + /* Check if we actually have all the octets */ + if(bytes_left<2+16) + return OP_FAILURE; + curr_pnt+=18; + bytes_left-=18; + break; + + /* Option Type Unknown */ + default: + /* If we don't know the option, we can still try to validate it, + * checking if the OptionLength contains something reasonable. */ + /* Fixed length of 16 */ + if(bytes_left<2+curr_opt->len) + return OP_FAILURE; + curr_pnt+=2+curr_opt->len; + bytes_left-=2+curr_opt->len; + break; + } + } + return this->length; +} /* End of validate() */ + + +/** Prints the contents of the header and calls print() on the next protocol + * header in the chain (if there is any). + * @return OP_SUCCESS on success and OP_FAILURE in case of error. */ +int HopByHopHeader::print(FILE *output, int detail) const { + fprintf(output, "HopByHop[%d,%d]", this->h.nh, this->h.len); + // TODO: @todo : Implement this + if(this->next!=NULL){ + print_separator(output, detail); + next->print(output, detail); + } + return OP_SUCCESS; +} /* End of print() */ + + +/******************************************************************************/ +/* PROTOCOL-SPECIFIC METHODS */ +/******************************************************************************/ + +/** Set Next Header field */ +int HopByHopHeader::setNextHeader(u8 val){ + this->h.nh = val; + return OP_SUCCESS; +} /* End of setNextHeader() */ + + +/** Returns next header id */ +u8 HopByHopHeader::getNextHeader(){ + return this->h.nh; +} /* End of getNextHeader() */ + + +/* Add TLV encoded option */ +int HopByHopHeader::addOption(u8 type, u8 len, const u8 *data){ + /* Make sure we don't screw up due to buffer length issues */ + if(data==NULL) + return OP_FAILURE; + if ( (this->length+len+2) > HOPBYHOP_MAX_HEADER_LEN ) /* No space for more */ + return OP_FAILURE; + + /* Store the option */ + curr_option[0]=type; + curr_option[1]=len; + memcpy(curr_option+2, data, len); + /* Update internal option offset and object's length */ + curr_option+=(len+2); + this->length+=(len+2); + this->addPadding(); + return OP_SUCCESS; + +} /* End of addOption() */ + + +/* If the current length of the extension header is not a multiple of 8 octets, + * this method adds the neccessary padding (either PadN or Pad1 options)*/ +int HopByHopHeader::addPadding(){ + u8 zeroes[8]={0,0,0,0,0,0,0,0}; + int required_octets=8-(this->length%8); + + /* Make sure we have enough space for the padding. */ + if ( (this->length+required_octets) > HOPBYHOP_MAX_HEADER_LEN ) + return OP_FAILURE; + + /* Insert Pad1 or PadN to fill the necessary octets */ + if(required_octets>0 && required_octets<8){ + if(required_octets==1){ + curr_option[0]=EXTOPT_PAD1; + curr_option++; + this->length++; + }else{ + this->addOption(EXTOPT_PADN, required_octets-2, zeroes ); + } + } + assert(this->length%8==0); + this->h.len=(this->length/8)-1; + return OP_SUCCESS; +} /* End of addPadding() */ diff --git a/libnetutil/HopByHopHeader.h b/libnetutil/HopByHopHeader.h new file mode 100644 index 0000000000..47ab9d51e8 --- /dev/null +++ b/libnetutil/HopByHopHeader.h @@ -0,0 +1,153 @@ + +/*************************************************************************** + * HopByHopHeader.h -- The HopByHopHeader Class represents an IPv6 * + * Hop-by-Hop extension header. * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#ifndef __HOP_BY_HOP_HEADER_H__ +#define __HOP_BY_HOP_HEADER_H__ 1 + +#include "IPv6ExtensionHeader.h" + +#define HOP_BY_HOP_MAX_OPTIONS_LEN 256*8 +#define HOPBYHOP_MIN_HEADER_LEN 8 +#define HOPBYHOP_MAX_HEADER_LEN (HOPBYHOP_MIN_HEADER_LEN + HOP_BY_HOP_MAX_OPTIONS_LEN) +#define HOPBYHOP_MAX_OPTION_LEN 256 + +class HopByHopHeader : public IPv6ExtensionHeader { + + protected: + /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Next Header | Hdr Ext Len | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + | | + . . + . Options . + . . + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + struct nping_ipv6_ext_hopbyhop_hdr{ + u8 nh; + u8 len; + u8 options[HOP_BY_HOP_MAX_OPTIONS_LEN]; + }__attribute__((__packed__)); + typedef struct nping_ipv6_ext_hopbyhop_hdr nping_ipv6_ext_hopbyhop_hdr_t; + + + /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - - - - - - - - + | Option Type | Opt Data Len | Option Data + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - - - - - - - - */ + struct nping_ipv6_ext_hopbyhop_opt{ + u8 type; + u8 len; + u8 data[HOPBYHOP_MAX_OPTION_LEN]; + }__attribute__((__packed__)); + typedef struct nping_ipv6_ext_hopbyhop_opt nping_ipv6_ext_hopbyhop_opt_t; + + nping_ipv6_ext_hopbyhop_hdr_t h; + u8 *curr_option; + + public: + HopByHopHeader(); + ~HopByHopHeader(); + void reset(); + u8 *getBufferPointer(); + int storeRecvData(const u8 *buf, size_t len); + int protocol_id() const; + int validate(); + int print(FILE *output, int detail) const; + + /* Protocol specific methods */ + int setNextHeader(u8 val); + u8 getNextHeader(); + + int addOption(u8 type, u8 len, const u8 *data); + int addPadding(); + +}; /* End of class HopByHopHeader */ + +#endif diff --git a/libnetutil/ICMPHeader.h b/libnetutil/ICMPHeader.h new file mode 100644 index 0000000000..76cd516efd --- /dev/null +++ b/libnetutil/ICMPHeader.h @@ -0,0 +1,114 @@ + +/*************************************************************************** + * ICMPHeader.h -- Class ICMPHeader is a generic class for the ICMP * + * protocol. Its aim is to provide a little bit of abstraction from the * + * underlying ICMP version. Classes like ICMPv4Header or ICMPv6Header * + * inherit from it. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2010 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#ifndef __ICMPHEADER_H__ +#define __ICMPHEADER_H__ 1 + +#include "PacketElement.h" + +class ICMPHeader : public PacketElement { + + public: + + virtual u8 getType() const = 0; + + virtual int setType(u8 val) = 0; + + virtual u8 getCode() const = 0; + + virtual int setCode(u8 val) = 0; + + virtual bool isError() const = 0; +}; + +#endif /* __ICMPHEADER_H__ */ diff --git a/libnetutil/ICMPv4Header.cc b/libnetutil/ICMPv4Header.cc new file mode 100755 index 0000000000..1f0dbf6f4c --- /dev/null +++ b/libnetutil/ICMPv4Header.cc @@ -0,0 +1,1209 @@ + +/*************************************************************************** + * ICMPv4Header.cc -- The ICMPv4Header Class represents an ICMP version 4 * + * packet. It contains methods to set any header field. In general, these * + * methods do error checkings and byte order conversion. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#include "ICMPv4Header.h" + +/******************************************************************************/ +/* CONTRUCTORS, DESTRUCTORS AND INITIALIZATION METHODS */ +/******************************************************************************/ +ICMPv4Header::ICMPv4Header() { + this->reset(); +} /* End of ICMPv4Header constructor */ + + +ICMPv4Header::~ICMPv4Header() { + +} /* End of ICMPv4Header destructor */ + + +/** Sets every attribute to its default value */ +void ICMPv4Header::reset(){ + memset(&this->h, 0, sizeof(nping_icmpv4_hdr_t)); + h_du = (icmp4_dest_unreach_msg_t *)this->h.data; + h_te = (icmp4_time_exceeded_msg_t *)this->h.data; + h_pp = (icmp4_parameter_problem_msg_t *)this->h.data; + h_sq = (icmp4_source_quench_msg_t *)this->h.data; + h_r = (icmp4_redirect_msg_t *)this->h.data; + h_e = (icmp4_echo_msg_t *)this->h.data; + h_t = (icmp4_timestamp_msg_t *)this->h.data; + h_i = (icmp4_information_msg_t *)this->h.data; + h_ra = (icmp4_router_advert_msg_t *)this->h.data; + h_rs = (icmp4_router_solicit_msg_t *)this->h.data; + h_sf = (icmp4_security_failures_msg_t *)this->h.data; + h_am = (icmp4_address_mask_msg_t *)this->h.data; + h_trc = (icmp4_traceroute_msg_t *)this->h.data; + h_dn = (icmp4_domain_name_request_msg_t *)this->h.data; + h_dnr = (icmp4_domain_name_reply_msg_t *)this->h.data; + this->routeradventries=0; + this->domainnameentries=0; +} /* End of reset() */ + + +/******************************************************************************/ +/* PacketElement:: OVERWRITTEN METHODS */ +/******************************************************************************/ + +/** @warning This method is essential for the superclass getBinaryBuffer() + * method to work. Do NOT change a thing unless you know what you're doing */ +u8 *ICMPv4Header::getBufferPointer(){ + return (u8*)(&h); +} /* End of getBufferPointer() */ + + +/** Stores supplied packet in the internal buffer so the information + * can be accessed using the standard get & set methods. + * @warning The ICMPv4Header class is able to hold a maximum of 1508 bytes. + * If the supplied buffer is longer than that, only the first 1508 bytes will + * be stored in the internal buffer. + * @warning Supplied len MUST be at least 8 bytes (min ICMPv4 header length). + * @return OP_SUCCESS on success and OP_FAILURE in case of error */ +int ICMPv4Header::storeRecvData(const u8 *buf, size_t len){ + if(buf==NULL || lenreset(); /* Re-init the object, just in case the caller had used it already */ + this->length=stored_len; + memcpy(&(this->h), buf, stored_len); + } + return OP_SUCCESS; +} /* End of storeRecvData() */ + + +/* Returns a protocol identifier. This is used by packet parsing funtions + * that return linked lists of PacketElement objects, to determine the protocol + * the object represents. */ +int ICMPv4Header::protocol_id() const { + return HEADER_TYPE_ICMPv4; +} /* End of protocol_id() */ + + +/** Determines if the data stored in the object after an storeRecvData() call + * is valid and safe to use. This mainly checks the length of the data but may + * also test the value of certain protocol fields to ensure their correctness. + * @return the length, in bytes, of the header, if its found to be valid or + * OP_FAILURE (-1) otherwise. */ +int ICMPv4Header::validate(){ + int should_have=this->getICMPHeaderLengthFromType( this->getType() ); + if(this->length < should_have){ + return OP_FAILURE; + }else{ + /* WARNING: TODO: @todo This does not work for those messages whose + * length is variable (e.g: router advertisements). */ + return should_have; + } +} /* End of validate() */ + + +/** Prints the contents of the header and calls print() on the next protocol + * header in the chain (if there is any). + * @return OP_SUCCESS on success and OP_FAILURE in case of error. */ +int ICMPv4Header::print(FILE *output, int detail) const { + u8 type=this->getType(); + u8 code=this->getCode(); + char auxstr[64]; + struct in_addr auxaddr; + const char *typestr=this->type2string(type, code); + + fprintf(output, "ICMPv4[%s", typestr); + if(detail>=PRINT_DETAIL_MED) + fprintf(output, " (type=%u/code=%u)", type, code); + + switch(type) { + case ICMP_ECHOREPLY: + case ICMP_ECHO: + case ICMP_INFO: + case ICMP_INFOREPLY: + fprintf(output, " id=%u seq=%u", this->getIdentifier(), this->getSequence()); + break; + + case ICMP_UNREACH: + case ICMP_SOURCEQUENCH: + case ICMP_ROUTERSOLICIT: + if(detail>=PRINT_DETAIL_HIGH) + fprintf(output, " unused=%u", this->getUnused()); + break; + + case ICMP_REDIRECT: + auxaddr=this->getGatewayAddress(); + inet_ntop(AF_INET, &auxaddr, auxstr, sizeof(auxstr)-1); + fprintf(output, " addr=%s", auxstr); + break; + + case ICMP_ROUTERADVERT: + fprintf(output, " addrs=%u addrlen=%u lifetime=%d", + this->getNumAddresses(), + this->getAddrEntrySize(), + this->getLifetime() + ); + break; + + case ICMP_PARAMPROB: + fprintf(output, " pointer=%u", this->getParameterPointer()); + break; + + case ICMP_TSTAMP: + case ICMP_TSTAMPREPLY: + fprintf(output, " id=%u seq=%u", this->getIdentifier(), this->getSequence()); + fprintf(output, " orig=%lu recv=%lu trans=%lu", + (unsigned long)this->getOriginateTimestamp(), + (unsigned long)this->getReceiveTimestamp(), + (unsigned long)this->getTransmitTimestamp() ); + break; + + case ICMP_MASK: + case ICMP_MASKREPLY: + fprintf(output, " id=%u seq=%u", this->getIdentifier(), this->getSequence()); + auxaddr=this->getAddressMask(); + inet_ntop(AF_INET, &auxaddr, auxstr, sizeof(auxstr)-1); + fprintf(output, " mask=%s", auxstr); + break; + + case ICMP_TRACEROUTE: + fprintf(output, " id=%u", this->getIDNumber()); + if(detail>=PRINT_DETAIL_HIGH) + fprintf(output, " unused=%u", this->getUnused()); + if(detail>=PRINT_DETAIL_MED){ + fprintf(output, " outhops=%u", this->getOutboundHopCount() ); + fprintf(output, " rethops=%u", this->getReturnHopCount() ); + } + if(detail>=PRINT_DETAIL_HIGH){ + fprintf(output, " speed=%lu", (unsigned long)this->getOutputLinkSpeed() ); + fprintf(output, " mtu=%lu", (unsigned long)this->getOutputLinkMTU()); + } + break; + + case ICMP_DOMAINNAME: + case ICMP_DOMAINNAMEREPLY: + fprintf(output, " id=%u seq=%u", this->getIdentifier(), this->getSequence()); + /* TODO: print TTL and domain names in replies */ + // UNIMPLEMENTED + break; + + case ICMP_SECURITYFAILURES: + if(detail>=PRINT_DETAIL_HIGH) + fprintf(output, " reserved=%u",this->getReserved()); + fprintf(output, " pointer=%u",this->getSecurityPointer()); + break; + + default: + /* Print nothing */ + break; + } + + if(detail>=PRINT_DETAIL_HIGH) + fprintf(output, " csum=0x%04X", ntohs(this->getSum())); + fprintf(output, "]"); + if(this->next!=NULL){ + print_separator(output, detail); + next->print(output, detail); + } + return OP_SUCCESS; +} /* End of print() */ + + +/******************************************************************************/ +/* PROTOCOL-SPECIFIC METHODS */ +/******************************************************************************/ + +/* ICMPv4 common fields *****************************************************/ +int ICMPv4Header::setType(u8 val){ + h.type = val; + length = getICMPHeaderLengthFromType( val ); + return OP_SUCCESS; +} /* End of setType() */ + + +/** @warning Returned value is in HOST byte order */ +u8 ICMPv4Header::getType() const { + return h.type; +} /* End of getType() */ + +/** Returns true if the supplied type is an RFC compliant type */ +bool ICMPv4Header::validateType(u8 val){ + switch( val ){ + case ICMP_ECHOREPLY: + case ICMP_UNREACH: + case ICMP_SOURCEQUENCH: + case ICMP_REDIRECT: + case ICMP_ECHO: + case ICMP_ROUTERADVERT: + case ICMP_ROUTERSOLICIT: + case ICMP_TIMXCEED: + case ICMP_PARAMPROB: + case ICMP_TSTAMP: + case ICMP_TSTAMPREPLY: + case ICMP_INFO: + case ICMP_INFOREPLY: + case ICMP_MASK: + case ICMP_MASKREPLY: + case ICMP_TRACEROUTE: + return true; + break; + + default: + return false; + break; + } + return false; +} /* End of validateType() */ + + +/** Returns true if the type fields contains an RFC compliant ICMP message + * type. */ +bool ICMPv4Header::validateType(){ + return validateType( this->h.type ); +} /* End of validateType() */ + + +/** Set ICMP code field */ +int ICMPv4Header::setCode(u8 val){ + h.code = val; + return OP_SUCCESS; +} /* End of setCode() */ + + +/** @warning Returned value is in HOST byte order */ +u8 ICMPv4Header::getCode() const { + return h.code; +} /* End of getCode() */ + + +/** Given an ICMP Type and a code, determines whether the code corresponds to + * a RFC compliant code (eg: code 0x03 for "port unreachable" in ICMP + * Unreachable messages) or just some other bogus code. */ +bool ICMPv4Header::validateCode(u8 type, u8 code){ + switch (type){ + case ICMP_ECHOREPLY: + return (code==0); + break; + + case ICMP_UNREACH: + switch( code ){ + case ICMP_UNREACH_NET: + case ICMP_UNREACH_HOST: + case ICMP_UNREACH_PROTOCOL: + case ICMP_UNREACH_PORT: + case ICMP_UNREACH_NEEDFRAG: + case ICMP_UNREACH_SRCFAIL: + case ICMP_UNREACH_NET_UNKNOWN: + case ICMP_UNREACH_HOST_UNKNOWN: + case ICMP_UNREACH_ISOLATED: + case ICMP_UNREACH_NET_PROHIB: + case ICMP_UNREACH_HOST_PROHIB: + case ICMP_UNREACH_TOSNET: + case ICMP_UNREACH_TOSHOST: + case ICMP_UNREACH_COMM_PROHIB: + case ICMP_UNREACH_HOSTPRECEDENCE: + case ICMP_UNREACH_PRECCUTOFF: + return true; + } + break; + + case ICMP_REDIRECT: + switch( code ){ + case ICMP_REDIRECT_NET: + case ICMP_REDIRECT_HOST: + case ICMP_REDIRECT_TOSNET: + case ICMP_REDIRECT_TOSHOST: + return true; + } + break; + + case ICMP_ROUTERADVERT: + switch( code ){ + case 0: + case ICMP_ROUTERADVERT_MOBILE: + return true; + } + break; + + case ICMP_TIMXCEED: + switch( code ){ + case ICMP_TIMXCEED_INTRANS: + case ICMP_TIMXCEED_REASS: + return true; + } + break; + + case ICMP_PARAMPROB: + switch( code ){ + case ICMM_PARAMPROB_POINTER: + case ICMP_PARAMPROB_OPTABSENT: + case ICMP_PARAMPROB_BADLEN: + return true; + } + break; + + case ICMP_TSTAMP: + case ICMP_TSTAMPREPLY: + case ICMP_INFO: + case ICMP_INFOREPLY: + case ICMP_MASK: + case ICMP_MASKREPLY: + case ICMP_ROUTERSOLICIT: + case ICMP_SOURCEQUENCH: + case ICMP_ECHO: + return (code==0); + break; + + case ICMP_TRACEROUTE: + switch( code ){ + case ICMP_TRACEROUTE_SUCCESS: + case ICMP_TRACEROUTE_DROPPED: + return true; + } + break; + + default: + return false; + break; + } + return false; +} /* End of validateCode() */ + + +/** Computes the ICMP header checksum and sets the checksum field to the right + * value. */ +int ICMPv4Header::setSum(){ + u8 buffer[65535]; + int total_len=0; + h.checksum = 0; + + memcpy(buffer, &h, length); + + if( this->getNextElement() != NULL) + total_len=next->dumpToBinaryBuffer(buffer+length, 65535-length); + total_len+=length; + + h.checksum = in_cksum((unsigned short *)buffer, total_len); + + return OP_SUCCESS; +} /* End of setSum() */ + + +/** @warning Sum is set to supplied value with NO byte ordering conversion + * performed. + * @warning If sum is supplied this way, no error checks are made. Caller is + * responsible for the correctness of the value. */ +int ICMPv4Header::setSum(u16 s){ + h.checksum = s; + return OP_SUCCESS; +} /* End of setSum() */ + + +/** Returns the value of the checksum field. + * @warning The returned value is in NETWORK byte order, no conversion is + * performed */ +u16 ICMPv4Header::getSum() const { + return h.checksum; +} /* End of getSum() */ + + + +/* Dest unreach/Source quench/Time exceeded **********************************/ +/** @warning Supplied value MUST be in host byte order because it will get + * converted by this method using htonl() */ +int ICMPv4Header::setReserved(u32 val){ + u32 aux32=0; + u8 *auxpnt=(u8 *)&aux32; + + switch(this->h.type){ + + case ICMP_UNREACH: + this->h_du->unused=htonl(val); + break; + + case ICMP_TIMXCEED: + this->h_te->unused=htonl(val); + break; + + case ICMP_PARAMPROB: + /* The reserved field in Parameter Problem messages is only + * 24-bits long so we convert the supplied value to big endian and + * use only the 24 least significant bits. */ + aux32=htonl(val); + this->h_pp->unused[0]=auxpnt[1]; + this->h_pp->unused[1]=auxpnt[2]; + this->h_pp->unused[2]=auxpnt[3]; + break; + + case ICMP_SOURCEQUENCH: + this->h_sq->unused=htonl(val); + break; + + case ICMP_ROUTERSOLICIT: + this->h_rs->reserved=htonl(val); + break; + + case ICMP_SECURITYFAILURES: + /* The reserved field in Security failure messages is only + * 16-bits long so we cast it to u16 first (callers are not supposed to + * pass values higher than 2^16) */ + this->h_sf->reserved= htons((u16)val); + break; + + case ICMP_TRACEROUTE: + /* The reserved field in Traceroute messages is only + * 16-bits long so we cast it to u16 first (callers are not supposed to + * pass values higher than 2^16) */ + this->h_trc->unused=htons((u16)val); + break; + + default: + return OP_FAILURE; + break; + } + return OP_SUCCESS; +} /* End of setReserved() */ + + +/** @warning Returned value is in host byte order */ +u32 ICMPv4Header::getReserved() const { + u32 aux32=0; + u8 *auxpnt=(u8 *)&aux32; + + switch(this->h.type){ + + case ICMP_UNREACH: + return ntohl(this->h_du->unused); + break; + + case ICMP_TIMXCEED: + return ntohl(this->h_te->unused); + break; + + case ICMP_PARAMPROB: + /* The unused field in Parameter Problem messages is only + * 24-bits long so we extract the stored value and convert it to host + * byte order. */ + auxpnt[0]=0; + auxpnt[1]=this->h_pp->unused[0]; + auxpnt[2]=this->h_pp->unused[1]; + auxpnt[3]=this->h_pp->unused[2]; + return ntohl(aux32); + break; + + case ICMP_SOURCEQUENCH: + return ntohl(this->h_sq->unused); + break; + + case ICMP_ROUTERSOLICIT: + return ntohl(this->h_rs->reserved); + break; + + case ICMP_SECURITYFAILURES: + /* The unused field in Security Failures messages is only + * 16-bits long so we extract the stored value and cast it to an u32 in + * host byte order */ + return (u32)ntohs(h_sf->reserved); + break; + + case ICMP_TRACEROUTE: + /* The reserved field in Traceroute messages is only + * 16-bits long so we extract the stored value and cast it to an u32 in + * host byte order */ + return (u32)ntohs(h_trc->unused); + break; + + default: + return OP_FAILURE; + break; + } + return OP_SUCCESS; +} /* End of setReserved() */ + + +int ICMPv4Header::setUnused(u32 val){ + return this->setReserved(val); +} /* End of setUnused() */ + + +u32 ICMPv4Header::getUnused() const { + return this->getReserved(); +} /* End of getUnused() */ + + +/* Redirect ******************************************************************/ +/** @warning Supplied IP MUST be in NETWORK byte order */ +int ICMPv4Header::setGatewayAddress(struct in_addr ipaddr){ + h_r->gateway_address=ipaddr; + return OP_SUCCESS; +} /* End of setPreferredRouter() */ + + +struct in_addr ICMPv4Header::getGatewayAddress() const { + return h_r->gateway_address; +} /* End of getPreferredRouter() */ + + + +/* Parameter problem *********************************************************/ +/** Sets pointer value in Parameter Problem messages */ +int ICMPv4Header::setParameterPointer(u8 val){ + h_pp->pointer=val; + return OP_SUCCESS; +} /* End of setParameterPointer() */ + + +/** @warning Returned value is in HOST byte order */ +u8 ICMPv4Header::getParameterPointer() const { + return h_pp->pointer; +} /* End of getParameterPointer() */ + + +/* Router Advertisement ******************************************************/ +int ICMPv4Header::setNumAddresses(u8 val){ + h_ra->num_addrs=val; + return OP_SUCCESS; +} /* End of setNumAddresses() */ + + +u8 ICMPv4Header::getNumAddresses() const { + return h_ra->num_addrs; +} /* End of getNumAddresses() */ + + +int ICMPv4Header::setAddrEntrySize(u8 val){ + h_ra->addr_entry_size=val; + return OP_SUCCESS; +} /* End of setAddrEntrySize() */ + + +/** @warning Returned value is in HOST byte order */ +u8 ICMPv4Header::getAddrEntrySize() const { + return h_ra->addr_entry_size; +} /* End of getAddrEntrySize() */ + + +/** @warning Supplied value MUST be in host byte order because it will get + * converted by this method using htons() */ +int ICMPv4Header::setLifetime(u16 val){ + h_ra->lifetime= htons(val); + return OP_SUCCESS; +} /* End of setLifetime() */ + + +/** @warning Returned value is in HOST byte order */ +u16 ICMPv4Header::getLifetime() const { + return ntohs( h_ra->lifetime ); +} /* End of getLifetime() */ + + +/** @warning Asummes entries have a length of 2*32bits and consist of + * two 32bit values. + * @warning This method automatically updates field "Number of addreses" + * calling this->setNumAddresses(). If you want to place a bogus number + * on such field, setNumAddresses() must be called AFTER any calls to + * addRouterAdvEntry() + * */ +int ICMPv4Header::addRouterAdvEntry(struct in_addr raddr, u32 pref){ + if ( this->routeradventries >= MAX_ROUTER_ADVERT_ENTRIES ) + return OP_FAILURE; + h_ra->adverts[this->routeradventries].router_addr=raddr; + h_ra->adverts[this->routeradventries].preference_level=htonl(pref); + this->routeradventries++; /* Update internal entry count */ + length += 8; /* Update total length of the ICMP packet */ + this->setNumAddresses( this->routeradventries ); /* Update number of addresses */ + return OP_SUCCESS; +} /* End of addRouterAdEntry() */ + + +u8 *ICMPv4Header::getRouterAdvEntries(int *num) const { + if( this->routeradventries <= 0 ) + return NULL; + if (num!=NULL) + *num = this->routeradventries; + return (u8*)h_ra->adverts; +} /* End of getRouterEntries() */ + + +/* Echo/Timestamp/Mask *******************************************************/ +/** @warning Supplied value MUST be in host byte order because it will get + * converted by this method using htons() */ +int ICMPv4Header::setIdentifier(u16 val){ + switch(this->h.type){ + case ICMP_ECHOREPLY: + case ICMP_ECHO: + h_e->identifier=htons(val); + break; + + case ICMP_TSTAMP: + case ICMP_TSTAMPREPLY: + h_t->identifier=htons(val); + break; + + case ICMP_INFO: + case ICMP_INFOREPLY: + h_i->identifier=htons(val); + break; + + case ICMP_MASK: + case ICMP_MASKREPLY: + h_am->identifier=htons(val); + break; + + case ICMP_DOMAINNAME: + h_dn->identifier=htons(val); + break; + + case ICMP_DOMAINNAMEREPLY: + h_dnr->identifier=htons(val); + break; + + default: + return OP_FAILURE; + break; + } + return OP_SUCCESS; +} /* End of setIdentifier() */ + + +/** @warning Returned value is in HOST byte order */ +u16 ICMPv4Header::getIdentifier() const { + switch(this->h.type){ + case ICMP_ECHOREPLY: + case ICMP_ECHO: + return ntohs(h_e->identifier); + break; + + case ICMP_TSTAMP: + case ICMP_TSTAMPREPLY: + return ntohs(h_t->identifier); + break; + + case ICMP_INFO: + case ICMP_INFOREPLY: + return ntohs(h_i->identifier); + break; + + case ICMP_MASK: + case ICMP_MASKREPLY: + return ntohs(h_am->identifier); + break; + + case ICMP_DOMAINNAME: + return ntohs(h_dn->identifier); + break; + + case ICMP_DOMAINNAMEREPLY: + return ntohs(h_dnr->identifier); + break; + + default: + return 0; + break; + } + return 0; +} /* End of getIdentifier() */ + + +/** @warning Supplied value MUST be in host byte order because it will get + * converted by this method using htons() */ +int ICMPv4Header::setSequence(u16 val){ + switch(this->h.type){ + case ICMP_ECHOREPLY: + case ICMP_ECHO: + h_e->sequence=htons(val); + break; + + case ICMP_TSTAMP: + case ICMP_TSTAMPREPLY: + h_t->sequence=htons(val); + break; + + case ICMP_INFO: + case ICMP_INFOREPLY: + h_i->sequence=htons(val); + break; + + case ICMP_MASK: + case ICMP_MASKREPLY: + h_am->sequence=htons(val); + break; + + case ICMP_DOMAINNAME: + h_dn->sequence=htons(val); + break; + + case ICMP_DOMAINNAMEREPLY: + h_dnr->sequence=htons(val); + break; + + default: + return OP_FAILURE; + break; + } + return OP_SUCCESS; +} /* End of setSequence() */ + + +/** @warning Returned value is in HOST byte order */ +u16 ICMPv4Header::getSequence() const { + switch(this->h.type){ + case ICMP_ECHOREPLY: + case ICMP_ECHO: + return ntohs(h_e->sequence); + break; + + case ICMP_TSTAMP: + case ICMP_TSTAMPREPLY: + return ntohs(h_t->sequence); + break; + + case ICMP_INFO: + case ICMP_INFOREPLY: + return ntohs(h_i->sequence); + break; + + case ICMP_MASK: + case ICMP_MASKREPLY: + return ntohs(h_am->sequence); + break; + + case ICMP_DOMAINNAME: + return ntohs(h_dn->sequence); + break; + + case ICMP_DOMAINNAMEREPLY: + return ntohs(h_dnr->sequence); + break; + + default: + return 0; + break; + } + return 0; +} /* End of getSequence() */ + + + +/* Timestamp only ************************************************************/ +/** @warning Supplied value MUST be in host byte order because it will get + * converted by this method using htonl() */ +int ICMPv4Header::setOriginateTimestamp(u32 val){ + h_t->originate_ts=htonl(val); + return OP_SUCCESS; +} /* End of setOriginateTimestamp() */ + + +/** @warning Returned value is in HOST byte order */ +u32 ICMPv4Header::getOriginateTimestamp() const { + return ntohl(h_t->originate_ts); +} /* End of getOriginateTimestamp() */ + + +/** @warning Supplied value MUST be in host byte order because it will get + * converted by this method using htonl() */ +int ICMPv4Header::setReceiveTimestamp(u32 val){ + h_t->receive_ts=htonl(val); + return OP_SUCCESS; +} /* End of setReceiveTimestamp() */ + + +/** @warning Returned value is in HOST byte order */ +u32 ICMPv4Header::getReceiveTimestamp() const { + return ntohl(h_t->receive_ts); +} /* End of getReceiveTimestamp() */ + + +/** @warning Supplied value MUST be in host byte order because it will get + * converted by this method using htonl() */ +int ICMPv4Header::setTransmitTimestamp(u32 val){ + h_t->transmit_ts=htonl(val); + return OP_SUCCESS; +} /* End of setTransmitTimestamp() */ + + +/** @warning Returned value is in HOST byte order */ +u32 ICMPv4Header::getTransmitTimestamp() const { + return ntohl(h_t->transmit_ts); +} /* End of getTransmitTimestamp() */ + + + +/* Mask only ****************************************************************/ +int ICMPv4Header::setAddressMask(struct in_addr ipaddr){ + h_am->address_mask=ipaddr; + return OP_SUCCESS; +} /* End of AddressMask() */ + + +struct in_addr ICMPv4Header::getAddressMask() const { + return h_am->address_mask; +} /* End of getAddressMask() */ + + + +/* Security Failures *********************************************************/ +int ICMPv4Header::setSecurityPointer(u16 val){ + h_sf->pointer=htons(val); + return OP_SUCCESS; +} /* End of setSecurityPointer() */ + + +u16 ICMPv4Header::getSecurityPointer() const { + return ntohs(h_sf->pointer); +} /* End of getSecurityPointer() */ + + + +/* Traceroute ****************************************************************/ +int ICMPv4Header::setIDNumber(u16 val){ + h_trc->id_number = htons(val); + return OP_SUCCESS; +} /* End of setIDNumber() */ + + +u16 ICMPv4Header::getIDNumber() const { + return ntohs(h_trc->id_number); +} /* End of getIDNumber() */ + + +int ICMPv4Header::setOutboundHopCount(u16 val){ + h_trc->outbound_hop_count = htons(val); + return OP_SUCCESS; +} /* End of setOutboundHopCount() */ + + +u16 ICMPv4Header::getOutboundHopCount() const { + return ntohs(h_trc->outbound_hop_count); +} /* End of getOutboundHopCount() */ + + +int ICMPv4Header::setReturnHopCount(u16 val){ + h_trc->return_hop_count = htons(val); + return OP_SUCCESS; +} /* End of seReturnHopCountt() */ + + +u16 ICMPv4Header::getReturnHopCount() const { + return ntohs(h_trc->return_hop_count); +} /* End of getReturnHopCount() */ + + +int ICMPv4Header::setOutputLinkSpeed(u32 val){ + h_trc->output_link_speed = htonl(val); + return OP_SUCCESS; +} /* End of setOutputLinkSpeed() */ + + +u32 ICMPv4Header::getOutputLinkSpeed() const { + return ntohl(h_trc->output_link_speed); +} /* End of getOutputLinkSpeed() */ + + +int ICMPv4Header::setOutputLinkMTU(u32 val){ + h_trc->output_link_mtu = htonl(val); + return OP_SUCCESS; +} /* End of setOutputLinkMTU() */ + + +u32 ICMPv4Header::getOutputLinkMTU() const { + return ntohl(h_trc->output_link_mtu); +} /* End of getOutputLinkMTU() */ + + +/* Miscellanious *************************************************************/ +/** Returns the standard ICMP header length for the supplied ICMP message type. + * @warning Return value corresponds strictly to the ICMP header, this is, + * the minimum length of the ICMP header, variable length payload is never + * included. For example, an ICMP Router Advertising has a fixed header of 8 + * bytes but then the packet contains a variable number of Router Addresses + * and Preference Levels, so while the length of that ICMP packet is + * 8bytes + ValueInFieldNumberOfAddresses*8, we only return 8 because we + * cannot guarantee that the NumberOfAddresses field has been set before + * the call to this method. Same applies to the rest of types. */ +int ICMPv4Header::getICMPHeaderLengthFromType( u8 type ) const { + + switch( type ){ + + case ICMP_ECHO: + case ICMP_ECHOREPLY: + return 8; /* (+ optional data) */ + break; + + case ICMP_UNREACH: + return 8; /* (+ payload) */ + break; + + case ICMP_SOURCEQUENCH: + return 8; /* (+ payload) */ + break; + + case ICMP_REDIRECT: + return 8; /* (+ payload) */ + break; + + case ICMP_ROUTERADVERT: + return 8; /* (+ value of NumAddr field * 8 ) */ + break; + + case ICMP_ROUTERSOLICIT: + return 8; + break; + + case ICMP_TIMXCEED: + return 8; /* (+ payload) */ + break; + + case ICMP_PARAMPROB: + return 8; /* (+ payload) */ + break; + + case ICMP_TSTAMP: + case ICMP_TSTAMPREPLY: + return 20; + break; + + case ICMP_INFO: + case ICMP_INFOREPLY: + return 8; + break; + + case ICMP_MASK: + case ICMP_MASKREPLY: + return 12; + break; + + case ICMP_TRACEROUTE: + return 20; + break; + + /* Packets with non RFC-Compliant types will be represented as + an 8-byte ICMP header, just like the types that don't include + additional info (time exceeded, router solicitation, etc) */ + default: + return 8; + break; + } + return 8; +} /* End of getICMPHeaderLengthFromType() */ + + +const char *ICMPv4Header::type2string(int type, int code) const { + switch(type) { + case ICMP_ECHOREPLY: + return "Echo reply"; + break; + + case ICMP_UNREACH: + switch(code) { + case ICMP_UNREACH_NET: return "Network unreachable"; break; + case ICMP_UNREACH_HOST: return "Host unreachable"; break; + case ICMP_UNREACH_PROTOCOL: return "Protocol unreachable"; break; + case ICMP_UNREACH_PORT: return "Port unreachable"; break; + case ICMP_UNREACH_NEEDFRAG: return "Fragmentation required"; break; + case ICMP_UNREACH_SRCFAIL: return "Source route failed"; break; + case ICMP_UNREACH_NET_UNKNOWN: return "Destination network unknown"; break; + case ICMP_UNREACH_HOST_UNKNOWN: return "Destination host unknown"; break; + case ICMP_UNREACH_ISOLATED: return "Source host isolated"; break; + case ICMP_UNREACH_NET_PROHIB: return "Network prohibited"; break; + case ICMP_UNREACH_HOST_PROHIB: return "Host prohibited"; break; + case ICMP_UNREACH_TOSNET: return "Network unreachable for TOS"; break; + case ICMP_UNREACH_TOSHOST: return "Host unreachable for TOS"; break; + case ICMP_UNREACH_COMM_PROHIB: return "Communication prohibited"; break; + case ICMP_UNREACH_HOSTPRECEDENCE: return "Precedence violation"; break; + case ICMP_UNREACH_PRECCUTOFF: return "Precedence cutoff"; break; + default: return "Destination unreachable (unknown code)"; break; + } /* End of ICMP Code switch */ + break; + + case ICMP_SOURCEQUENCH: + return "Source quench"; + break; + + case ICMP_REDIRECT: + switch(code){ + case ICMP_REDIRECT_NET: return "Network redirect"; break; + case ICMP_REDIRECT_HOST: return "Host redirect"; break; + default: return "Redirect (unknown code)"; break; + } + break; + + case ICMP_ECHO: + return "Echo request"; + break; + + case ICMP_ROUTERADVERT: + switch(code){ + case ICMP_ROUTERADVERT_MOBILE: return "Router advertisement (Mobile Agent Only)"; break; + default: return "Router advertisement"; break; + } + break; + + case ICMP_ROUTERSOLICIT: + return "Router solicitation"; + break; + + case ICMP_TIMXCEED: + switch(code){ + case ICMP_TIMXCEED_INTRANS: return "TTL=0 during transit"; break; + case ICMP_TIMXCEED_REASS: return "TTL=0 during reassembly"; break; + default: return "TTL exceeded (unknown code)"; break; + } + break; + + case ICMP_PARAMPROB: + switch(code){ + case ICMM_PARAMPROB_POINTER: return "Parameter problem (pointer indicates error)"; break; + case ICMP_PARAMPROB_OPTABSENT: return "Parameter problem (option missing)"; break; + case ICMP_PARAMPROB_BADLEN: return "Parameter problem (bad length)"; break; + default: return "Parameter problem (unknown code)"; break; + } + break; + + case ICMP_TSTAMP: + return "Timestamp request"; + break; + + case ICMP_TSTAMPREPLY: + return "Timestamp reply"; + break; + + case ICMP_INFO: + return "Information request"; + break; + + case ICMP_INFOREPLY: + return "Information reply"; + break; + + case ICMP_MASK: + return "Address mask request "; + break; + + case ICMP_MASKREPLY: + return "Address mask reply"; + break; + + case ICMP_TRACEROUTE: + return "Traceroute"; + break; + + case ICMP_DOMAINNAME: + return "Domain name request"; + break; + + case ICMP_DOMAINNAMEREPLY: + return "Domain name reply"; + break; + + case ICMP_SECURITYFAILURES: + return "Security failures"; + break; + + default: + return "Unknown ICMP type"; + break; + } /* End of ICMP Type switch */ + return "Unknown ICMP type"; +} /* End of type2string() */ + + +/* Returns true if the packet is an ICMPv4 error message. */ +bool ICMPv4Header::isError() const { + switch( this->getType() ){ + case ICMP_UNREACH: + case ICMP_TIMXCEED: + case ICMP_PARAMPROB: + case ICMP_SOURCEQUENCH: + case ICMP_REDIRECT: + case ICMP_SECURITYFAILURES: + return true; + break; + + default: + return false; + break; + } +} /* End of isError() */ diff --git a/libnetutil/ICMPv4Header.h b/libnetutil/ICMPv4Header.h new file mode 100755 index 0000000000..130c2c27b6 --- /dev/null +++ b/libnetutil/ICMPv4Header.h @@ -0,0 +1,561 @@ + +/*************************************************************************** + * ICMPv4Header.h -- The ICMPv4Header Class represents an ICMP version 4 * + * packet. It contains methods to set any header field. In general, these * + * methods do error checkings and byte order conversion. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#ifndef ICMPv4HEADER_H +#define ICMPv4HEADER_H 1 + +#include "ICMPHeader.h" + +/* ICMP types and codes. These defines were originally taken from Slirp 1.0 + * source file ip_icmp.h http://slirp.sourceforge.net/ (BSD licensed) and + * then, partially modified for Nping */ +#define ICMP_ECHOREPLY 0 /* Echo reply */ +#define ICMP_UNREACH 3 /* Destination unreachable: */ +#define ICMP_UNREACH_NET 0 /* --> Bad network */ +#define ICMP_UNREACH_HOST 1 /* --> Bad host */ +#define ICMP_UNREACH_PROTOCOL 2 /* --> Bad protocol */ +#define ICMP_UNREACH_PORT 3 /* --> Bad port */ +#define ICMP_UNREACH_NEEDFRAG 4 /* --> DF flag caused pkt drop */ +#define ICMP_UNREACH_SRCFAIL 5 /* --> Source route failed */ +#define ICMP_UNREACH_NET_UNKNOWN 6 /* --> Unknown network */ +#define ICMP_UNREACH_HOST_UNKNOWN 7 /* --> Unknown host */ +#define ICMP_UNREACH_ISOLATED 8 /* --> Source host isolated */ +#define ICMP_UNREACH_NET_PROHIB 9 /* --> Prohibited access */ +#define ICMP_UNREACH_HOST_PROHIB 10 /* --> Prohibited access */ +#define ICMP_UNREACH_TOSNET 11 /* --> Bad TOS for network */ +#define ICMP_UNREACH_TOSHOST 12 /* --> Bad TOS for host */ +#define ICMP_UNREACH_COMM_PROHIB 13 /* --> Prohibited communication */ +#define ICMP_UNREACH_HOSTPRECEDENCE 14 /* --> Host precedence violation */ +#define ICMP_UNREACH_PRECCUTOFF 15 /* --> Precedence cutoff */ +#define ICMP_SOURCEQUENCH 4 /* Source Quench. */ +#define ICMP_REDIRECT 5 /* Redirect: */ +#define ICMP_REDIRECT_NET 0 /* --> For the network */ +#define ICMP_REDIRECT_HOST 1 /* --> For the host */ +#define ICMP_REDIRECT_TOSNET 2 /* --> For the TOS and network */ +#define ICMP_REDIRECT_TOSHOST 3 /* --> For the TOS and host */ +#define ICMP_ECHO 8 /* Echo request */ +#define ICMP_ROUTERADVERT 9 /* Router advertisement */ +#define ICMP_ROUTERADVERT_MOBILE 16 /* Used by mobile IP agents */ +#define ICMP_ROUTERSOLICIT 10 /* Router solicitation */ +#define ICMP_TIMXCEED 11 /* Time exceeded: */ +#define ICMP_TIMXCEED_INTRANS 0 /* --> TTL==0 in transit */ +#define ICMP_TIMXCEED_REASS 1 /* --> TTL==0 in reassembly */ +#define ICMP_PARAMPROB 12 /* Parameter problem */ +#define ICMM_PARAMPROB_POINTER 0 /* --> Pointer shows the problem */ +#define ICMP_PARAMPROB_OPTABSENT 1 /* --> Option missing */ +#define ICMP_PARAMPROB_BADLEN 2 /* --> Bad datagram length */ +#define ICMP_TSTAMP 13 /* Timestamp request */ +#define ICMP_TSTAMPREPLY 14 /* Timestamp reply */ +#define ICMP_INFO 15 /* Information request */ +#define ICMP_INFOREPLY 16 /* Information reply */ +#define ICMP_MASK 17 /* Address mask request */ +#define ICMP_MASKREPLY 18 /* Address mask reply */ +#define ICMP_TRACEROUTE 30 /* Traceroute */ +#define ICMP_TRACEROUTE_SUCCESS 0 /* --> Dgram sent to next router */ +#define ICMP_TRACEROUTE_DROPPED 1 /* --> Dgram was dropped */ +#define ICMP_DOMAINNAME 37 /* Domain name request */ +#define ICMP_DOMAINNAMEREPLY 38 /* Domain name reply */ +#define ICMP_SECURITYFAILURES 40 /* Security failures */ + + +#define ICMP_STD_HEADER_LEN 8 +#define ICMP_MAX_PAYLOAD_LEN 1500 +#define MAX_ROUTER_ADVERT_ENTRIES (((ICMP_MAX_PAYLOAD_LEN-4)/8)-1) + + +class ICMPv4Header : public ICMPHeader { + + private: + + /**********************************************************************/ + /* COMMON ICMPv4 packet HEADER */ + /**********************************************************************/ + /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + Message Body + + | | */ + struct nping_icmpv4_hdr { + u8 type; /* ICMP Message Type */ + u8 code; /* ICMP Message Code */ + u16 checksum; /* Checksum */ + u8 data[ICMP_MAX_PAYLOAD_LEN]; + }__attribute__((__packed__)); + typedef struct nping_icmpv4_hdr nping_icmpv4_hdr_t; + + + /**********************************************************************/ + /* ICMPv4 MESSAGE SPECIFIC HEADERS */ + /**********************************************************************/ + + /* Destination Unreachable Message + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | unused | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Internet Header + 64 bits of Original Data Datagram | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + struct icmp4_dest_unreach_msg{ + u32 unused; + //u8 original_dgram[?]; + }__attribute__((__packed__)); + typedef struct icmp4_dest_unreach_msg icmp4_dest_unreach_msg_t; + + + /* Time Exceeded Message + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | unused | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Internet Header + 64 bits of Original Data Datagram | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + struct icmp4_time_exceeded_msg{ + u32 unused; + //u8 original_dgram[?]; + }__attribute__((__packed__)); + typedef struct icmp4_time_exceeded_msg icmp4_time_exceeded_msg_t; + + + /* Parameter Problem Message + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Pointer | unused | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Internet Header + 64 bits of Original Data Datagram | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + + struct icmp4_parameter_problem_msg{ + u8 pointer; + u8 unused[3]; + //u8 original_dgram[?]; + }__attribute__((__packed__)); + typedef struct icmp4_parameter_problem_msg icmp4_parameter_problem_msg_t; + + + /* Source Quench Message + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | unused | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Internet Header + 64 bits of Original Data Datagram | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + struct icmp4_source_quench_msg{ + u32 unused; + //u8 original_dgram[?]; + }__attribute__((__packed__)); + typedef struct icmp4_source_quench_msg icmp4_source_quench_msg_t; + + + /* Redirect Message + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Gateway Internet Address | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Internet Header + 64 bits of Original Data Datagram | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + struct icmp4_redirect_msg{ + struct in_addr gateway_address; + //u8 original_dgram[?]; + }__attribute__((__packed__)); + typedef struct icmp4_redirect_msg icmp4_redirect_msg_t; + + + /* Echo Request/Reply Message + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Identifier | Sequence Number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Data ... + +-+-+-+-+- */ + struct icmp4_echo_msg{ + u16 identifier; + u16 sequence; + //u8 data[?]; + }__attribute__((__packed__)); + typedef struct icmp4_echo_msg icmp4_echo_msg_t; + + + /* Timestamp Request/Reply Message + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Identifier | Sequence Number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Originate Timestamp | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Receive Timestamp | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Transmit Timestamp | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + struct icmp4_timestamp_msg{ + u16 identifier; + u16 sequence; + u32 originate_ts; + u32 receive_ts; + u32 transmit_ts; + }__attribute__((__packed__)); + typedef struct icmp4_timestamp_msg icmp4_timestamp_msg_t; + + + /* Information Request/Reply Message + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Identifier | Sequence Number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + struct icmp4_information_msg{ + u16 identifier; + u16 sequence; + }__attribute__((__packed__)); + typedef struct icmp4_information_msg icmp4_information_msg_t; + + + /* ICMP Router Advertisement Message + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Num Addrs |Addr Entry Size| Lifetime | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Router Address[1] | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Preference Level[1] | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Router Address[2] | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Preference Level[2] | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | . | + | . | + | . | */ + struct icmp4_router_advert_entry{ + struct in_addr router_addr; + u32 preference_level; + }__attribute__((__packed__)); + typedef struct icmp4_router_advert_entry icmp4_router_advert_entry_t; + + struct icmp4_router_advert_msg{ + u8 num_addrs; + u8 addr_entry_size; + u16 lifetime; + icmp4_router_advert_entry_t adverts[MAX_ROUTER_ADVERT_ENTRIES]; + }__attribute__((__packed__)); + typedef struct icmp4_router_advert_msg icmp4_router_advert_msg_t; + + + /* ICMP Router Solicitation Message + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Reserved | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + struct icmp4_router_solicit_msg{ + u32 reserved; + }__attribute__((__packed__)); + typedef struct icmp4_router_solicit_msg icmp4_router_solicit_msg_t; + + + /* ICMP Security Failures Message + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Reserved | Pointer | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + ~ Original Internet Headers + 64 bits of Payload ~ + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + struct icmp4_security_failures_msg{ + u16 reserved; + u16 pointer; + //u8 original_headers[?]; + }__attribute__((__packed__)); + typedef struct icmp4_security_failures_msg icmp4_security_failures_msg_t; + + + /* ICMP Address Mask Request/Reply Message + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Identifier | Sequence Number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Address Mask | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + struct icmp4_address_mask_msg{ + u16 identifier; + u16 sequence; + struct in_addr address_mask; + }__attribute__((__packed__)); + typedef struct icmp4_address_mask_msg icmp4_address_mask_msg_t; + + + /* ICMP Traceroute Message + +---------------+---------------+---------------+---------------+ + | Type | Code | Checksum | + +---------------+---------------+---------------+---------------+ + | ID Number | unused | + +---------------+---------------+---------------+---------------+ + | Outbound Hop Count | Return Hop Count | + +---------------+---------------+---------------+---------------+ + | Output Link Speed | + +---------------+---------------+---------------+---------------+ + | Output Link MTU | + +---------------+---------------+---------------+---------------+ */ + struct icmp4_traceroute_msg{ + u16 id_number; + u16 unused; + u16 outbound_hop_count; + u16 return_hop_count; + u32 output_link_speed; + u32 output_link_mtu; + }__attribute__((__packed__)); + typedef struct icmp4_traceroute_msg icmp4_traceroute_msg_t; + + + /* ICMP Domain Name Request Message + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Identifier | Sequence Number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + struct icmp4_domain_name_request_msg{ + u16 identifier; + u16 sequence; + }__attribute__((__packed__)); + typedef struct icmp4_domain_name_request_msg icmp4_domain_name_request_msg_t; + + + /* ICMP Domain Name Reply Message + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Identifier | Sequence Number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Time-To-Live | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Names ... + +-+-+-+-+-+-+-+- */ + struct icmp4_domain_name_reply_msg{ + u16 identifier; + u16 sequence; + s16 ttl; /* Signed! */ + u8 names[ICMP_MAX_PAYLOAD_LEN-8]; + }__attribute__((__packed__)); + typedef struct icmp4_domain_name_reply_msg icmp4_domain_name_reply_msg_t; + + + /* Main data structure */ + nping_icmpv4_hdr_t h; + + /* Helper pointers */ + icmp4_dest_unreach_msg_t *h_du; + icmp4_time_exceeded_msg_t *h_te; + icmp4_parameter_problem_msg_t *h_pp; + icmp4_source_quench_msg_t *h_sq; + icmp4_redirect_msg_t *h_r; + icmp4_echo_msg_t *h_e; + icmp4_timestamp_msg_t *h_t; + icmp4_information_msg_t *h_i; + icmp4_router_advert_msg_t *h_ra; + icmp4_router_solicit_msg_t *h_rs; + icmp4_security_failures_msg_t *h_sf; + icmp4_address_mask_msg_t *h_am; + icmp4_traceroute_msg_t *h_trc; + icmp4_domain_name_request_msg_t *h_dn; + icmp4_domain_name_reply_msg_t *h_dnr; + + /* Internal counts */ + int routeradventries; + int domainnameentries; + + public: + /* PacketElement:: Mandatory methods */ + ICMPv4Header(); + ~ICMPv4Header(); + void reset(); + u8 *getBufferPointer(); + int storeRecvData(const u8 *buf, size_t len); + int protocol_id() const; + int validate(); + int print(FILE *output, int detail) const; + + /* ICMP Type */ + int setType(u8 val); + u8 getType() const; + bool validateType(); + bool validateType(u8 val); + + /* ICMP Code */ + int setCode(u8 c); + u8 getCode() const; + bool validateCode(); + bool validateCode(u8 type, u8 code); + + /* Checksum */ + int setSum(); + int setSum(u16 s); + u16 getSum() const; + + /* Unused and reserved fields */ + int setUnused(u32 val); + u32 getUnused() const; + int setReserved( u32 val ); + u32 getReserved() const; + + /* Redirect */ + int setGatewayAddress(struct in_addr ipaddr); + struct in_addr getGatewayAddress() const; + + /* Parameter problem */ + int setParameterPointer(u8 val); + u8 getParameterPointer() const; + + /* Router advertisement */ + int setNumAddresses(u8 val); + u8 getNumAddresses() const; + int setAddrEntrySize(u8 val); + u8 getAddrEntrySize() const; + int setLifetime(u16 val); + u16 getLifetime() const; + int addRouterAdvEntry(struct in_addr raddr, u32 pref); + u8 *getRouterAdvEntries(int *num) const; + int clearRouterAdvEntries(); + + /* Echo/Timestamp/Mask */ + int setIdentifier(u16 val); + u16 getIdentifier() const; + int setSequence(u16 val); + u16 getSequence() const; + + /* Timestamp only */ + int setOriginateTimestamp(u32 t); + u32 getOriginateTimestamp() const; + int setReceiveTimestamp(u32 t); + u32 getReceiveTimestamp() const; + int setTransmitTimestamp(u32 t); + u32 getTransmitTimestamp() const; + + /* Mask only */ + int setAddressMask(struct in_addr mask); + struct in_addr getAddressMask() const; + + /* Security Failures */ + int setSecurityPointer(u16 val); + u16 getSecurityPointer() const; + + /* Traceroute */ + int setIDNumber(u16 val); + u16 getIDNumber() const; + int setOutboundHopCount(u16 val); + u16 getOutboundHopCount() const; + int setReturnHopCount(u16 val); + u16 getReturnHopCount() const; + int setOutputLinkSpeed(u32 val); + u32 getOutputLinkSpeed() const; + int setOutputLinkMTU(u32 val); + u32 getOutputLinkMTU() const; + + /* Misc */ + int getICMPHeaderLengthFromType( u8 type ) const; + const char *type2string(int type, int code) const; + bool isError() const; + + +}; /* End of class ICMPv4Header */ + +#endif diff --git a/libnetutil/ICMPv6Header.cc b/libnetutil/ICMPv6Header.cc new file mode 100755 index 0000000000..abafa7e132 --- /dev/null +++ b/libnetutil/ICMPv6Header.cc @@ -0,0 +1,1158 @@ + +/*************************************************************************** + * ICMPv6Header.cc -- The ICMPv6Header Class represents an ICMP version 6 * + * packet. It contains methods to set any header field. In general, these * + * methods do error checkings and byte order conversion. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#include "ICMPv6Header.h" +#include "IPv6Header.h" +#include + +/******************************************************************************/ +/* CONTRUCTORS, DESTRUCTORS AND INITIALIZATION METHODS */ +/******************************************************************************/ +ICMPv6Header::ICMPv6Header() { + this->reset(); +} /* End of ICMPv6Header constructor */ + + +ICMPv6Header::~ICMPv6Header() { + +} /* End of ICMPv6Header destructor */ + + +/** Sets every attribute to its default value */ +void ICMPv6Header::reset(){ + memset(&this->h, 0, sizeof(nping_icmpv6_hdr_t)); + h_du = (dest_unreach_msg_t *)this->h.data; + h_ptb= (pkt_too_big_msg_t *)this->h.data; + h_te = (time_exceeded_msg_t *)this->h.data; + h_pp = (parameter_problem_msg_t *)this->h.data; + h_e = (echo_msg_t *)this->h.data; + h_ra = (router_advert_msg_t *)this->h.data; + h_rs = (router_solicit_msg_t *)this->h.data; + h_na = (neighbor_advert_msg_t *)this->h.data; + h_ns = (neighbor_solicit_msg_t *)this->h.data; + h_r = (redirect_msg_t *)this->h.data; + h_rr = (router_renumbering_msg_t *)this->h.data; + h_ni = (nodeinfo_msg_t *)this->h.data; + h_mld= (mld_msg_t *)this->h.data; +} /* End of reset() */ + + +/******************************************************************************/ +/* PacketElement:: OVERWRITTEN METHODS */ +/******************************************************************************/ + +/** @warning This method is essential for the superclass getBinaryBuffer() + * method to work. Do NOT change a thing unless you know what you're doing */ +u8 *ICMPv6Header::getBufferPointer(){ + return (u8*)(&this->h); +} /* End of getBufferPointer() */ + + +/** Stores supplied packet in the internal buffer so the information + * can be accessed using the standard get & set methods. + * @warning The ICMPv6Header class is able to hold a maximum of + * sizeof(nping_icmpv6_hdr_t) bytes. If the supplied buffer is longer than + * that, only the first 1508 bytes will be stored in the internal buffer. + * @warning Supplied len MUST be at least 8 bytes (min ICMPv6 header length). + * @return OP_SUCCESS on success and OP_FAILURE in case of error */ +int ICMPv6Header::storeRecvData(const u8 *buf, size_t len){ + if(buf==NULL || lenlength=0; + return OP_FAILURE; + }else{ + int stored_len = MIN( sizeof(nping_icmpv6_hdr_t), len); + this->reset(); /* Re-init the object, just in case the caller had used it already */ + this->length=stored_len; + memcpy(&(this->h), buf, stored_len); + } + return OP_SUCCESS; +} /* End of storeRecvData() */ + + +/* Returns a protocol identifier. This is used by packet parsing funtions + * that return linked lists of PacketElement objects, to determine the protocol + * the object represents. */ +int ICMPv6Header::protocol_id() const { + return HEADER_TYPE_ICMPv6; +} /* End of protocol_id() */ + + +/** Determines if the data stored in the object after an storeRecvData() call + * is valid and safe to use. This mainly checks the length of the data but may + * also test the value of certain protocol fields to ensure their correctness. + * @return the length, in bytes, of the header, if its found to be valid or + * OP_FAILURE (-1) otherwise. */ +int ICMPv6Header::validate(){ + int should_have=this->getHeaderLengthFromType( this->getType() ); + if(this->length < should_have){ + return OP_FAILURE; + }else{ + /* WARNING: If we extend this class to support new ICMPv6 types with + * a variable length header (not even sure they exist), we need to + * parse the objects data and return our actual size, not this size that + * is obtained from the type. */ + return should_have; + } +} /* End of validate() */ + + +/** Prints the contents of the header and calls print() on the next protocol + * header in the chain (if there is any). + * @return OP_SUCCESS on success and OP_FAILURE in case of error. */ +int ICMPv6Header::print(FILE *output, int detail) const { + fprintf(output, "ICMPv6[]"); + if(this->next!=NULL){ + print_separator(output, detail); + next->print(output, detail); + } + return OP_SUCCESS; +} /* End of print() */ + + +/******************************************************************************/ +/* PROTOCOL-SPECIFIC METHODS */ +/******************************************************************************/ + +/******************************************************************************/ +/* ICMPv6 COMMON HEADER */ +/******************************************************************************/ + +/** Set ICMPv6 type field */ +int ICMPv6Header::setType(u8 val){ + this->h.type = val; + this->length = getHeaderLengthFromType(val); + return OP_SUCCESS; +} /* End of setType() */ + + +/** Returns ICMPv6 type field */ +u8 ICMPv6Header::getType() const { + return this->h.type; +} /* End of getType() */ + + +/* Returns true if the supplied ICMPv6 type is supported by this class */ +bool ICMPv6Header::validateType(u8 val){ + switch( val ){ + case ICMPv6_UNREACH: + case ICMPv6_PKTTOOBIG: + case ICMPv6_TIMXCEED: + case ICMPv6_PARAMPROB: + case ICMPv6_ECHO: + case ICMPv6_ECHOREPLY: + case ICMPv6_ROUTERSOLICIT: + case ICMPv6_ROUTERADVERT: + case ICMPv6_NGHBRSOLICIT: + case ICMPv6_NGHBRADVERT: + case ICMPv6_REDIRECT: + case ICMPv6_RTRRENUM: + return true; + break; + + default: + return false; + break; + } + return false; +} /* End of validateType() */ + + +bool ICMPv6Header::validateType(){ + return validateType(this->h.type); +} /* End of validateType() */ + + +/** Set ICMPv6 code field */ +int ICMPv6Header::setCode(u8 val){ + this->h.code = val; + return OP_SUCCESS; +} /* End of setCode() */ + + +/** Returns ICMPv6 code field */ +u8 ICMPv6Header::getCode() const { + return this->h.code; +} /* End of getCode() */ + + +/** Given an ICMP Type and a code, determines whether the code corresponds to + * a RFC compliant code (eg: code 0x03 for "port unreachable" in ICMP + * Unreachable messages) or just some other bogus code. */ +bool ICMPv6Header::validateCode(u8 type, u8 code){ +// switch (type){ +// +// case ICMPv6_UNREACH: +// return (code==0); +// break; +// +// case ICMPv6_PKTTOOBIG: +// switch( code ){ +// case XXXXXXXXXXXX: +// case YYYYYYYYYYYY: +// case ZZZZZZZZZZZZ: +// return true; +// break; +// } +// break; +// +// case ICMPv6_TIMXCEED: +// +// break; +// +// case ICMPv6_PARAMPROB: +// +// break; +// +// case ICMPv6_ECHO: +// +// break; +// +// case ICMPv6_ECHOREPLY: +// +// break; +// +// case ICMPv6_ROUTERSOLICIT: +// case ICMPv6_ROUTERADVERT: +// case ICMPv6_NGHBRSOLICIT: +// case ICMPv6_NGHBRADVERT: +// case ICMPv6_REDIRECT: +// break; +// +// default: +// return false; +// break; +// } + return false; +} /* End of validateCode() */ + + +/** Computes the ICMP header checksum and sets the checksum field to the right + * value. + * @warning This method requires the ICMPv6Object to be linked to an IPv6Header + * object, so make sure setNextElement() has been called like this: + * + * IPv6Header ip6; + * ICMPv6Header icmp6; + * [...] # Set header fields + * ip6.setNextElement(&icmp6); + * icmp6.setSum(); + * + * Note that there can be a number of extension headers between the ICMPv6 + * header and the IPv6 one, but all of them need to be linked in order for this + * method to traverse the list of headers and find the IPv6 source and + * destination address, required to compute the checksum. So things like the + * following are OK: + * + * IPv6Header ip6; + * HopByHopHeader hop; + * RoutingHeader rte; + * FragmentHeader frg; + * ICMPv6Header icmp6; + * [...] # Set whatever header fields you need + * ip6.setNextElement(&hop); + * hop.setNextElement(&rte); + * rte.setNextElement(&frg); + * frg.setNextElement(&icmp6); + * icmp6.setSum(); # setSum() will be able to reach the IPv6Header. + * + */ +int ICMPv6Header::setSum(){ + PacketElement *hdr; + hdr=this->getPrevElement(); + /* Traverse the list of headers backwards until we find the IPv6 header */ + while(hdr!=NULL){ + if (hdr->protocol_id()==HEADER_TYPE_IPv6){ + IPv6Header *v6hdr=(IPv6Header *)hdr; + struct in6_addr i6src, i6dst; + this->h.checksum=0; + memcpy(i6src.s6_addr, v6hdr->getSourceAddress(), 16); + memcpy(i6dst.s6_addr, v6hdr->getDestinationAddress(), 16); + u8 *buff=(u8 *)safe_malloc(this->getLen()); + this->dumpToBinaryBuffer(buff, this->getLen()); + this->h.checksum=ipv6_pseudoheader_cksum(&i6src, &i6dst, this->protocol_id(), this->getLen(), buff); + free(buff); + return OP_SUCCESS; + }else{ + hdr=hdr->getPrevElement(); + } + } + return OP_FAILURE; +} /* End of setSum() */ + + +/** @warning Sum is set to supplied value with NO byte ordering conversion + * performed. + * @warning If sum is supplied this way, no error checks are made. Caller is + * responsible for the correctness of the value. */ +int ICMPv6Header::setSum(u16 s){ + this->h.checksum=s; + return OP_SUCCESS; +} /* End of setSum() */ + + +/** Returns the value of the checksum field. + * @warning The returned value is in NETWORK byte order, no conversion is + * performed */ +u16 ICMPv6Header::getSum(){ + return this->h.checksum; +} /* End of getSum() */ + + +/** @warning Supplied value MUST be in host byte order because it will get + * converted by this method using htonl() */ +int ICMPv6Header::setReserved(u32 val){ + u32 aux32=0; + u8 *auxpnt=(u8 *)&aux32; + + switch(this->h.type){ + + case ICMPv6_UNREACH: + this->h_du->unused=htonl(val); + break; + + case ICMPv6_TIMXCEED: + this->h_te->unused=htonl(val); + break; + + case ICMPv6_ROUTERSOLICIT: + this->h_rs->reserved=htonl(val); + break; + + case ICMPv6_NGHBRSOLICIT: + this->h_ns->reserved=htonl(val); + break; + + case ICMPv6_REDIRECT: + this->h_r->reserved=htonl(val); + break; + + + case ICMPv6_NGHBRADVERT: + /* The reserved field in Neighbor Advertisement messages is only + * 24-bits long so we convert the supplied value to big endian and + * use only the 24 least significant bits. */ + aux32=htonl(val); + this->h_na->reserved[0]=auxpnt[1]; + this->h_na->reserved[1]=auxpnt[2]; + this->h_na->reserved[2]=auxpnt[3]; + break; + + case ICMPv6_RTRRENUM: + this->h_rr->reserved=htonl(val); + break; + + /* Types that don't have a reserved field */ + case ICMPv6_ROUTERADVERT: + case ICMPv6_ECHO: + case ICMPv6_ECHOREPLY: + case ICMPv6_PARAMPROB: + case ICMPv6_PKTTOOBIG: + default: + return OP_FAILURE; + break; + } + return OP_SUCCESS; +} /* End of setReserved() */ + + +/** @warning Returned value is in host byte order */ +u32 ICMPv6Header::getReserved(){ + u32 aux32=0; + u8 *auxpnt=(u8 *)&aux32; + + switch(this->h.type){ + + case ICMPv6_UNREACH: + return ntohl(this->h_du->unused); + break; + + case ICMPv6_TIMXCEED: + return ntohl(this->h_te->unused); + break; + + case ICMPv6_ROUTERSOLICIT: + return ntohl(this->h_rs->reserved); + break; + + case ICMPv6_NGHBRSOLICIT: + return ntohl(this->h_ns->reserved); + break; + + case ICMPv6_REDIRECT: + return ntohl(this->h_r->reserved); + break; + + case ICMPv6_NGHBRADVERT: + /* The reserved field in Neighbor Advertisement messages is only + * 24-bits long so we extract the stored value and convert it to host + * byte order. */ + auxpnt[0]=0; + auxpnt[1]=this->h_na->reserved[0]; + auxpnt[2]=this->h_na->reserved[1]; + auxpnt[3]=this->h_na->reserved[2]; + return ntohl(aux32); + break; + + case ICMPv6_RTRRENUM: + return ntohl(this->h_rr->reserved); + break; + + /* Types that don't have a reserved field */ + case ICMPv6_ROUTERADVERT: + case ICMPv6_ECHO: + case ICMPv6_ECHOREPLY: + case ICMPv6_PARAMPROB: + case ICMPv6_PKTTOOBIG: + default: + return 0; + break; + } +} /* End of setReserved() */ + +int ICMPv6Header::setUnused(u32 val){ + return this->setReserved(val); +} /* End of setUnused() */ + + +u32 ICMPv6Header::getUnused(){ + return this->getReserved(); +} /* End of getUnused() */ + + +int ICMPv6Header::setFlags(u8 val){ + switch(this->h.type){ + + case ICMPv6_ROUTERADVERT: + this->h_ra->autoconfig_flags=val; + break; + + case ICMPv6_NGHBRADVERT: + this->h_na->flags=val; + break; + + case ICMPv6_RTRRENUM: + this->h_rr->flags=val; + break; + + case ICMPv6_NODEINFOQUERY: + case ICMPv6_NODEINFORESP: + netutil_fatal("setFlags() cannot be used in NI, use setNodeInfoFlags() instead\n"); + break; + + /* Types that don't have a flags field */ + case ICMPv6_TIMXCEED: + case ICMPv6_UNREACH: + case ICMPv6_ROUTERSOLICIT: + case ICMPv6_NGHBRSOLICIT: + case ICMPv6_REDIRECT: + case ICMPv6_ECHO: + case ICMPv6_ECHOREPLY: + case ICMPv6_PARAMPROB: + case ICMPv6_PKTTOOBIG: + default: + return OP_FAILURE; + break; + } + return OP_SUCCESS; +} /* End of setFlags() */ + + +u8 ICMPv6Header::getFlags(){ + switch(this->h.type){ + + case ICMPv6_ROUTERADVERT: + return this->h_ra->autoconfig_flags; + break; + + case ICMPv6_NGHBRADVERT: + return this->h_na->flags; + break; + + case ICMPv6_RTRRENUM: + return this->h_rr->flags; + break; + + case ICMPv6_NODEINFOQUERY: + case ICMPv6_NODEINFORESP: + netutil_fatal("getFlags() cannot be used in NI, use getNodeInfoFlags() instead\n"); + return 0; + break; + + /* Types that don't have a flags field */ + case ICMPv6_TIMXCEED: + case ICMPv6_UNREACH: + case ICMPv6_ROUTERSOLICIT: + case ICMPv6_NGHBRSOLICIT: + case ICMPv6_REDIRECT: + case ICMPv6_ECHO: + case ICMPv6_ECHOREPLY: + case ICMPv6_PARAMPROB: + case ICMPv6_PKTTOOBIG: + default: + return 0; + break; + } +} /* End of getFlags() */ + +/******************************************************************************/ +/* ICMPv6 DESTINATION UNREACHABLE */ +/******************************************************************************/ + +/******************************************************************************/ +/* ICMPv6 PACKET TOO BIG */ +/******************************************************************************/ +int ICMPv6Header::setMTU(u32 mtu){ + this->h_ptb->mtu=htonl(mtu); + return OP_SUCCESS; +} /* End of setMTU() */ + +u32 ICMPv6Header::getMTU(){ + return ntohl(this->h_ptb->mtu); +} /* End of getMTU() */ + +/******************************************************************************/ +/* ICMPv6 TIME EXCEEDED */ +/******************************************************************************/ + +/******************************************************************************/ +/* ICMPv6 PARAMETER PROBLEM */ +/******************************************************************************/ +int ICMPv6Header::setPointer(u32 pnt){ + this->h_pp->pointer=htonl(pnt); + return OP_SUCCESS; +} /* End of setPointer() */ + + +u32 ICMPv6Header::getPointer(){ + return ntohl(this->h_pp->pointer); +} /* End of getPointer() */ + +/******************************************************************************/ +/* ICMPv6 ECHO */ +/******************************************************************************/ +int ICMPv6Header::setIdentifier(u16 val){ + this->h_e->id=htons(val); + return OP_SUCCESS; +} /* End of setIdentifier() */ + + +u16 ICMPv6Header::getIdentifier(){ + return ntohs(this->h_e->id); +} /* End of getIdentifier() */ + + +int ICMPv6Header::setSequence(u16 val){ + switch(this->h.type){ + case ICMPv6_RTRRENUM: + this->h_rr->seq=htonl( ((u32)val) ); + break; + + case ICMPv6_ECHO: + case ICMPv6_ECHOREPLY: + this->h_e->seq=htons(val); + break; + + default: + return OP_FAILURE; + break; + } + return OP_SUCCESS; +} /* End of setSequence() */ + + +int ICMPv6Header::setSequence(u32 val){ + switch(this->h.type){ + case ICMPv6_RTRRENUM: + this->h_rr->seq=htonl(val); + break; + + case ICMPv6_ECHO: + case ICMPv6_ECHOREPLY: + this->h_e->seq=htons( ((u16)val) ); + break; + + default: + return OP_FAILURE; + break; + } + return OP_SUCCESS; +} /* End of setSequence() */ + + +u32 ICMPv6Header::getSequence(){ + switch(this->h.type){ + case ICMPv6_RTRRENUM: + return ntohl(this->h_rr->seq); + break; + + case ICMPv6_ECHO: + case ICMPv6_ECHOREPLY: + return ntohl( ((u32)this->h_e->seq) ); + break; + } + return 0; +} /* End of getSequence() */ + + +/******************************************************************************/ +/* ICMPv6 ROUTER ADVERTISEMENT */ +/******************************************************************************/ +int ICMPv6Header::setCurrentHopLimit(u8 val){ + this->h_ra->current_hop_limit=val; + return OP_SUCCESS; +} /* End of setCurrentHopLimit() */ + +u8 ICMPv6Header::getCurrentHopLimit(){ + return this->h_ra->current_hop_limit; +} /* End of getCurrentHopLimit() */ + +int ICMPv6Header::setRouterLifetime(u16 val){ + this->h_ra->router_lifetime=val; + return OP_SUCCESS; +} /* End of setRouterLifetime() */ + +u16 ICMPv6Header::getRouterLifetime(){ + return this->h_ra->router_lifetime; +} /* End of getRouterLifetime() */ + +int ICMPv6Header::setReachableTime(u32 val){ + this->h_ra->reachable_time=val; + return OP_SUCCESS; +} /* End of setReachableTime() */ + +u32 ICMPv6Header::getReachableTime(){ + return this->h_ra->reachable_time; +} /* End of getReachableTime() */ + +int ICMPv6Header::setRetransmissionTimer(u32 val){ + this->h_ra->retransmission_timer=val; + return OP_SUCCESS; +} /* End of setRetransmissionTimer() */ + +u32 ICMPv6Header::getRetransmissionTimer(){ + return this->h_ra->retransmission_timer; +} /* End of getRetransmissionTimer() */ + +/******************************************************************************/ +/* ICMPv6 ROUTER SOLICITATION */ +/******************************************************************************/ + +/******************************************************************************/ +/* ICMPv6 NEIGHBOR ADVERTISEMENT */ +/******************************************************************************/ + +int ICMPv6Header::setTargetAddress(struct in6_addr addr){ + switch(this->h.type){ + case ICMPv6_NGHBRADVERT: + memcpy(this->h_na->target_address, addr.s6_addr, 16); + break; + + case ICMPv6_NGHBRSOLICIT: + memcpy(this->h_ns->target_address, addr.s6_addr, 16); + break; + + case ICMPv6_REDIRECT: + memcpy(this->h_r->target_address, addr.s6_addr, 16); + break; + + default: + return OP_FAILURE; + break; + } + return OP_SUCCESS; +} /* End of setTargetAddress() */ + + +struct in6_addr ICMPv6Header::getTargetAddress(){ + struct in6_addr addr; + memset(&addr, 0, sizeof(struct in6_addr)); + + switch(this->h.type){ + case ICMPv6_NGHBRADVERT: + memcpy(addr.s6_addr, this->h_na->target_address, 16); + break; + + case ICMPv6_NGHBRSOLICIT: + memcpy(addr.s6_addr, this->h_ns->target_address, 16); + break; + + case ICMPv6_REDIRECT: + memcpy(addr.s6_addr, this->h_r->target_address, 16); + break; + } + return addr; +} /* End of setTargetAddress() */ + + +int ICMPv6Header::setDestinationAddress(struct in6_addr addr){ + switch(this->h.type){ + case ICMPv6_REDIRECT: + memcpy(this->h_r->destination_address, addr.s6_addr, 16); + break; + + default: + return OP_FAILURE; + break; + } + return OP_SUCCESS; +} /* End of setDestinationAddress() */ + + +struct in6_addr ICMPv6Header::getDestinationAddress(){ + struct in6_addr addr; + memset(&addr, 0, sizeof(struct in6_addr)); + + switch(this->h.type){ + case ICMPv6_REDIRECT: + memcpy(addr.s6_addr, this->h_r->destination_address, 16); + break; + } + return addr; +} /* End of setTargetAddress() */ + + +/******************************************************************************/ +/* ICMPv6 NEIGHBOR SOLICITATION */ +/******************************************************************************/ + +/******************************************************************************/ +/* ICMPv6 REDIRECT */ +/******************************************************************************/ + +/******************************************************************************/ +/* ICMPv6 ROUTER RENUMBERING */ +/******************************************************************************/ +int ICMPv6Header::setSegmentNumber(u8 val){ + this->h_rr->segment_number=val; + return OP_SUCCESS; +} /* End of setSegmentNumber() */ + +u8 ICMPv6Header::getSegmentNumber(){ + return this->h_rr->segment_number; +} /* End of getSegmentNumber() */ + +int ICMPv6Header::setMaxDelay(u16 val){ + switch(this->h.type){ + case ICMPv6_RTRRENUM: + this->h_rr->max_delay=htons(val); + return OP_SUCCESS; + break; + + case ICMPv6_GRPMEMBQUERY: + case ICMPv6_GRPMEMBREP: + case ICMPv6_GRPMEMBRED: + this->h_mld->max_response_delay=htons(val); + return OP_SUCCESS; + break; + + default: + return OP_FAILURE; + break; + } +} /* End of setMaxDelay() */ + + +u16 ICMPv6Header::getMaxDelay(){ + switch(this->h.type){ + case ICMPv6_RTRRENUM: + return ntohs(this->h_rr->max_delay); + break; + + case ICMPv6_GRPMEMBQUERY: + case ICMPv6_GRPMEMBREP: + case ICMPv6_GRPMEMBRED: + return ntohs(this->h_mld->max_response_delay); + break; + + default: + return 0; + break; + } +} /* End of getMaxDelay() */ + + + +/******************************************************************************/ +/* ICMPv6 NODE INFORMATION QUERIES */ +/******************************************************************************/ +/** Set NI Qtype */ +int ICMPv6Header::setQtype(u16 val){ + this->h_ni->qtype = htons(val); + return OP_SUCCESS; +} /* End of setQtype() */ + + +/** Returns NI Qtype */ +u16 ICMPv6Header::getQtype(){ + return ntohs(this->h_ni->qtype); +} /* End of getQtype() */ + + +/** Set NI Flags */ +int ICMPv6Header::setNodeInfoFlags(u16 val){ + this->h_ni->flags = htons(val); + return OP_SUCCESS; +} /* End of setNodeInfoFlags() */ + + +/** Returns NI Flags */ +u16 ICMPv6Header::getNodeInfoFlags(){ + return ntohs(this->h_ni->flags); +} /* End of getNodeInfoFlags() */ + + +/* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | unused |G|S|L|C|A|T| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + +/* Set NI Flag G */ +int ICMPv6Header::setG(bool flag_value){ + u16 current_flags = this->getNodeInfoFlags(); + if(flag_value) + current_flags = current_flags | 0x0020; + else + current_flags = current_flags & ~0x0020; + this->setNodeInfoFlags(current_flags); + return OP_SUCCESS; +} /* End of setG() */ + + +/* Get NI Flag G */ +bool ICMPv6Header::getG(){ + return this->getNodeInfoFlags() & 0x0020; +} /* End of getG() */ + + +/* Set NI Flag S */ +int ICMPv6Header::setS(bool flag_value){ + u16 current_flags = this->getNodeInfoFlags(); + if(flag_value) + current_flags = current_flags | 0x0010; + else + current_flags = current_flags & ~0x0010; + this->setNodeInfoFlags(current_flags); + return OP_SUCCESS; +} /* End of setS() */ + + +/* Get NI Flag S */ +bool ICMPv6Header::getS(){ + return this->getNodeInfoFlags() & 0x0010; +} /* End of getS() */ + + +/* Set NI Flag L */ +int ICMPv6Header::setL(bool flag_value){ + u16 current_flags = this->getNodeInfoFlags(); + if(flag_value) + current_flags = current_flags | 0x0008; + else + current_flags = current_flags & ~0x0008; + this->setNodeInfoFlags(current_flags); + return OP_SUCCESS; +} /* End of setL() */ + + +/* Get NI Flag L */ +bool ICMPv6Header::getL(){ + return this->getNodeInfoFlags() & 0x0008; +} /* End of getL() */ + + +/* Set NI Flag C */ +int ICMPv6Header::setC(bool flag_value){ + u16 current_flags = this->getNodeInfoFlags(); + if(flag_value) + current_flags = current_flags | 0x0004; + else + current_flags = current_flags & ~0x0004; + this->setNodeInfoFlags(current_flags); + return OP_SUCCESS; +} /* End of setC() */ + + +/* Get NI Flag C */ +bool ICMPv6Header::getC(){ + return this->getNodeInfoFlags() & 0x0004; +} /* End of getC() */ + + +/* Set NI Flag A */ +int ICMPv6Header::setA(bool flag_value){ + u16 current_flags = this->getNodeInfoFlags(); + if(flag_value) + current_flags = current_flags | 0x0002; + else + current_flags = current_flags & ~0x0002; + this->setNodeInfoFlags(current_flags); + return OP_SUCCESS; +} /* End of setA() */ + + +/* Get NI Flag A */ +bool ICMPv6Header::getA(){ + return this->getNodeInfoFlags() & 0x0002; +} /* End of getA() */ + + +/* Set NI Flag T */ +int ICMPv6Header::setT(bool flag_value){ + u16 current_flags = this->getNodeInfoFlags(); + if(flag_value) + current_flags = current_flags | 0x0001; + else + current_flags = current_flags & ~0x0001; + this->setNodeInfoFlags(current_flags); + return OP_SUCCESS; +} /* End of setT() */ + + +/* Get NI Flag T */ +bool ICMPv6Header::getT(){ + return this->getNodeInfoFlags() & 0x0001; +} /* End of getT() */ + + +/* Set the Nonce field. + * @warning: Supplied buffer must contain 8 bytes. */ +int ICMPv6Header::setNonce(const u8 *nonce){ + if(nonce==NULL) + return OP_FAILURE; + memcpy(this->h_ni->nonce, nonce, NI_NONCE_LEN); + return OP_SUCCESS; +} /* End of setNonce() */ + + +/* Returns a pointer to the nonce buffer. + * @warning: The returned pointer is guaranteed to point to an 8-byte buffer. + * However, what comes after the 8th byte is unspecified. */ +u8 *ICMPv6Header::getNonce(){ + return this->h_ni->nonce; +} /* End of getNonce() */ + + +/******************************************************************************/ +/* MULTICAST LISTENER DISCOVERY */ +/******************************************************************************/ + +int ICMPv6Header::setMulticastAddress(struct in6_addr addr){ + switch(this->h.type){ + case ICMPv6_GRPMEMBQUERY: + case ICMPv6_GRPMEMBREP: + case ICMPv6_GRPMEMBRED: + memcpy(this->h_mld->mcast_address, addr.s6_addr, 16); + break; + + default: + return OP_FAILURE; + break; + } + + return OP_SUCCESS; +} /* End of setMulticastAddress() */ + + +struct in6_addr ICMPv6Header::getMulticastAddress(){ + struct in6_addr addr; + memset(&addr, 0, sizeof(struct in6_addr)); + + switch(this->h.type){ + case ICMPv6_GRPMEMBQUERY: + case ICMPv6_GRPMEMBREP: + case ICMPv6_GRPMEMBRED: + memcpy(addr.s6_addr, this->h_mld->mcast_address, 16); + break; + } + return addr; +} /* End of setMulticastAddress() */ + + +/******************************************************************************/ +/* MISCELLANEOUS STUFF */ +/******************************************************************************/ + +/** Returns the standard ICMPv6 header length for the supplied ICMP message type. + * @warning Return value corresponds strictly to the ICMP header, this is, + * the minimum length of the ICMP header, variable length payload is never + * included. For example, an ICMPv6 Redirect has a fixed header of 40 + * bytes but then the packet may contain ICMPv6 options. We only return 40 + * because we don't know in advance the total number of bytes for the message. + * Same applies to the rest of types. */ +int ICMPv6Header::getHeaderLengthFromType(u8 type){ + + switch( type ){ + case ICMPv6_UNREACH: + return ICMPv6_UNREACH_LEN; + break; + case ICMPv6_PKTTOOBIG: + return ICMPv6_PKTTOOBIG_LEN; + break; + + case ICMPv6_TIMXCEED: + return ICMPv6_TIMXCEED_LEN; + break; + + case ICMPv6_PARAMPROB: + return ICMPv6_PARAMPROB_LEN; + break; + + case ICMPv6_ECHO: + return ICMPv6_ECHO_LEN; + break; + + case ICMPv6_ECHOREPLY: + return ICMPv6_ECHOREPLY_LEN; + break; + + case ICMPv6_ROUTERSOLICIT: + return ICMPv6_ROUTERSOLICIT_LEN; + break; + + case ICMPv6_ROUTERADVERT: + return ICMPv6_ROUTERADVERT_LEN; + break; + + case ICMPv6_NGHBRSOLICIT: + return ICMPv6_NGHBRSOLICIT_LEN; + break; + + case ICMPv6_NGHBRADVERT: + return ICMPv6_NGHBRADVERT_LEN; + break; + + case ICMPv6_REDIRECT: + return ICMPv6_REDIRECT_LEN; + break; + + case ICMPv6_RTRRENUM: + return ICMPv6_RTRRENUM_LEN; + break; + + case ICMPv6_NODEINFOQUERY: + case ICMPv6_NODEINFORESP: + return ICMPv6_NODEINFO_LEN; + break; + + case ICMPv6_GRPMEMBQUERY: + case ICMPv6_GRPMEMBREP: + case ICMPv6_GRPMEMBRED: + return ICMPv6_MLD_LEN; + break; + + /* Packets with non RFC-Compliant types will be represented as an 8-byte + * ICMPv6 header, just like the types that don't include additional info */ + default: + return ICMPv6_MIN_HEADER_LEN; + break; + } +} /* End of getHeaderLengthFromType() */ + + +/* Returns true if the packet is an ICMPv6 error message. */ +bool ICMPv6Header::isError() const { + switch( this->getType() ){ + case ICMPv6_UNREACH: + case ICMPv6_PKTTOOBIG: + case ICMPv6_TIMXCEED: + case ICMPv6_PARAMPROB: + return true; + break; + + default: + return false; + break; + } +} /* End of isError() */ + + + diff --git a/libnetutil/ICMPv6Header.h b/libnetutil/ICMPv6Header.h new file mode 100755 index 0000000000..c9ae6fe87a --- /dev/null +++ b/libnetutil/ICMPv6Header.h @@ -0,0 +1,690 @@ + +/*************************************************************************** + * ICMPv6Header.h -- The ICMPv6Header Class represents an ICMP version 6 * + * packet. It contains methods to set any header field. In general, these * + * methods do error checkings and byte order conversion. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#ifndef ICMPv6HEADER_H +#define ICMPv6HEADER_H 1 + +#include "ICMPHeader.h" + +/******************************************************************************/ +/* IMPORTANT INFORMATION ON HOW TO USE THIS CLASS. */ +/******************************************************************************/ +/* This class represents an ICMPv6 messages. ICMPv6 messages may be of + * different types. Each type has its own header and possibly a variable + * length data field. Information messages have an "invoking packet" field + * which is the IP packet that triggered the emission of the ICMPv6 message. + * Other messages may contain a "data" field, like echo requests an replies. + * Some others may contain ICMPv6 Options. + * + * So the thing is, that this class only represents fixed-length ICMPv6 + * headers and does NOT offer storage for ANY variable-length field. This + * fields may be added to the ICMPv6 header using instances of the RawData + * class the ICMPv6Option class or even the IPv6Header class (in those cases + * where a whole packet is appendend to the ICMPv6 message). + * + * So, how does this work? Let's look at some examples. + * + * 1. Imagine we need to build an ICMP echo request message that includes some + * arbitrary data to be echoed. We could do the following: + * + * u8 final_packet[1024]; <-- Buffer to store the resulting packet + * u32 final_packet_len=0; <-- Length of the resulting packet + * ICMPv6Header header; <-- The ICMPv6 fixed-length part + * RawData data; <-- The data to append to the echo message + * + * header.setType(ICMPv6_ECHO); <-- Set ICMPv6 type to "Echo request" + * data.store("1234567890"); <-- Store data we need to send. + * header.setNextElement(&data); <-- Tell ICMPv6Header what's after it + * header.setSum(); <-- Compute the checksum + * + * final_packet_len=header.dumpToBinaryBuffer(fina_packet, 1024); + * send_packet(final_packet, final_packet_len) + * + * 2. If we are sending a parameter problem message and we need to include the + * invoking datagram, we can call setNextElement() passing an IPv6Header + * pointer. + * + * u8 final_packet[1024]; <-- Buffer to store the resulting packet + * u32 final_packet_len=0; <-- Length of the resulting packet + * ICMPv6Header header; <-- The ICMPv6 fixed-length part + * IPv6Header ipv6; <-- The IPv6 packet that triggered ICMPv6 + * + * header.setType(ICMPv6_PARAMPROB); <-- Set ICMPv6 type to "Param Problem" + * header.setNextElement(&ipv6); <-- Tell ICMPv6Header what's after it + * header.setSum(); <-- Compute the checksum + * + * Note that here we don't show how the ipv6 object is set. + * + * 3. If we are sending a router solicitation message, we'll call + * setNextElement() passing an IPv6Options Pointer. + * + * u8 final_packet[1024]; <-- Buffer to store the resulting packet + * u32 final_packet_len=0; <-- Length of the resulting packet + * ICMPv6Header header; <-- The ICMPv6 fixed-length part + * IPv6Options opts1; <-- IPv6 options + * IPv6Options opts2; <-- IPv6 options + * IPv6Options opts3; <-- IPv6 options + * + * header.setType(ICMPv6_ROUTERSOLICIT); <-- Set ICMPv6 type + * + * opts1.setXXXX(); <-- Set up the options + * . + * . + * . + * opts3.setYYYY(); + * + * opts2.setNextElement(&opts3); <-- Link the options + * opts1.setNextElement(&opts2); + * header.setNextElement(&opts1); + * header.setNextElement(&ipv6); <-- Link the first option to the ICMPv6 + * header.setSum(); <-- Compute the checksum + * + * And so on... + * + */ + + +/* Packet header diagrams included in this file have been taken from the + * following IETF RFC documents: RFC 4443, RFC 2461, RFC 2894 */ + +/* ICMP types and codes. + * The following types and codes have been defined by IANA. A complete list + * may be found at http://www.iana.org/assignments/icmpv6-parameters + * + * Definitions on the first level of indentation are ICMPv6 Types. + * Definitions on the second level of indentation (values enclosed in + * parenthesis) are ICMPv6 Codes */ +#define ICMPv6_UNREACH 1 /* Destination unreachable [RFC 2463, 4443] */ +#define ICMPv6_UNREACH_NO_ROUTE (0) /* --> No route to destination */ +#define ICMPv6_UNREACH_PROHIBITED (1) /* --> Communication administratively prohibited */ +#define ICMPv6_UNREACH_BEYOND_SCOPE (2) /* --> Beyond scope of source address [RFC4443] */ +#define ICMPv6_UNREACH_ADDR_UNREACH (3) /* --> Address unreachable */ +#define ICMPv6_UNREACH_PORT_UNREACH (4) /* --> Port unreachable */ +#define ICMPv6_UNREACH_SRC_ADDR_FAILED (5) /* --> Source address failed ingress/egress policy [RFC4443] */ +#define ICMPv6_UNREACH_REJECT_ROUTE (6) /* --> Reject route to destination [RFC4443] */ +#define ICMPv6_PKTTOOBIG 2 /* Packet too big [RFC 2463, 4443] */ +#define ICMPv6_TIMXCEED 3 /* Time exceeded [RFC 2463, 4443] */ +#define ICMPv6_TIMXCEED_HOP_EXCEEDED (0) /* --> Hop limit exceeded in transit */ +#define ICMPv6_TIMXCEED_REASS_EXCEEDED (1) /* --> Fragment reassembly time exceeded */ +#define ICMPv6_PARAMPROB 4 /* Parameter problem [RFC 2463, 4443] */ +#define ICMPv6_PARAMPROB_FIELD (0) /* --> Erroneous header field encountered */ +#define ICMPv6_PARAMPROB_NEXT_HDR (1) /* --> Unrecognized Next Header type encountered */ +#define ICMPv6_PARAMPROB_OPTION (2) /* --> Unrecognized IPv6 option encountered */ +#define ICMPv6_ECHO 128 /* Echo request [RFC 2463, 4443] */ +#define ICMPv6_ECHOREPLY 129 /* Echo reply [RFC 2463, 4443] */ +#define ICMPv6_GRPMEMBQUERY 130 /* Group Membership Query [RFC 2710] */ +#define ICMPv6_GRPMEMBREP 131 /* Group Membership Report [RFC 2710] */ +#define ICMPv6_GRPMEMBRED 132 /* Group Membership Reduction [RFC 2710] */ +#define ICMPv6_ROUTERSOLICIT 133 /* Router Solicitation [RFC 2461] */ +#define ICMPv6_ROUTERADVERT 134 /* Router Advertisement [RFC 2461] */ +#define ICMPv6_NGHBRSOLICIT 135 /* Neighbor Solicitation [RFC 2461] */ +#define ICMPv6_NGHBRADVERT 136 /* Neighbor Advertisement [RFC 2461] */ +#define ICMPv6_REDIRECT 137 /* Redirect [RFC 2461] */ +#define ICMPv6_RTRRENUM 138 /* Router Renumbering [RFC 2894] */ +#define ICMPv6_RTRRENUM_COMMAND (0) /* --> Router Renumbering Command */ +#define ICMPv6_RTRRENUM_RESULT (1) /* --> Router Renumbering Result */ +#define ICMPv6_RTRRENUM_SEQ_RESET (255) /* Sequence Number Reset */ +#define ICMPv6_NODEINFOQUERY 139 /* ICMP Node Information Query [RFC 4620] */ +#define ICMPv6_NODEINFOQUERY_IPv6ADDR (0) /* --> The Data field contains an IPv6 address */ +#define ICMPv6_NODEINFOQUERY_NAME (1) /* --> The Data field contains a name */ +#define ICMPv6_NODEINFOQUERY_IPv4ADDR (2) /* --> The Data field contains an IPv4 address */ +#define ICMPv6_NODEINFORESP 140 /* ICMP Node Information Response [RFC 4620] */ +#define ICMPv6_NODEINFORESP_SUCCESS (0) /* --> A successful reply. */ +#define ICMPv6_NODEINFORESP_REFUSED (1) /* --> The Responder refuses to supply the answer */ +#define ICMPv6_NODEINFORESP_UNKNOWN (2) /* --> The Qtype of the Query is unknown */ +#define ICMPv6_INVNGHBRSOLICIT 141 /* Inverse Neighbor Discovery Solicitation Message [RFC 3122] */ +#define ICMPv6_INVNGHBRADVERT 142 /* Inverse Neighbor Discovery Advertisement Message [RFC 3122] */ +#define ICMPv6_MLDV2 143 /* MLDv2 Multicast Listener Report [RFC 3810] */ +#define ICMPv6_AGENTDISCOVREQ 144 /* Home Agent Address Discovery Request Message [RFC 3775] */ +#define ICMPv6_AGENTDISCOVREPLY 145 /* Home Agent Address Discovery Reply Message [RFC 3775] */ +#define ICMPv6_MOBPREFIXSOLICIT 146 /* Mobile Prefix Solicitation [RFC 3775] */ +#define ICMPv6_MOBPREFIXADVERT 147 /* Mobile Prefix Advertisement [RFC 3775] */ +#define ICMPv6_CERTPATHSOLICIT 148 /* Certification Path Solicitation [RFC 3971] */ +#define ICMPv6_CERTPATHADVERT 149 /* Certification Path Advertisement [RFC 3971] */ +#define ICMPv6_EXPMOBILITY 150 /* Experimental mobility protocols [RFC 4065] */ +#define ICMPv6_MRDADVERT 151 /* MRD, Multicast Router Advertisement [RFC 4286] */ +#define ICMPv6_MRDSOLICIT 152 /* MRD, Multicast Router Solicitation [RFC 4286] */ +#define ICMPv6_MRDTERMINATE 153 /* MRD, Multicast Router Termination [RFC 4286] */ +#define ICMPv6_FMIPV6 154 /* FMIPv6 messages [RFC 5568] */ + +/* Node Information parameters */ +/* -> Query types */ +#define NI_QTYPE_NOOP 0 +#define NI_QTYPE_UNUSED 1 +#define NI_QTYPE_NODENAME 2 +#define NI_QTYPE_NODEADDRS 3 +#define NI_QTYPE_IPv4ADDRS 4 +/* -> Misc */ +#define NI_NONCE_LEN 8 + +/* Nping ICMPv6Header Class internal definitions */ +#define ICMPv6_COMMON_HEADER_LEN 4 +#define ICMPv6_MIN_HEADER_LEN 8 +#define ICMPv6_UNREACH_LEN (ICMPv6_COMMON_HEADER_LEN+4) +#define ICMPv6_PKTTOOBIG_LEN (ICMPv6_COMMON_HEADER_LEN+4) +#define ICMPv6_TIMXCEED_LEN (ICMPv6_COMMON_HEADER_LEN+4) +#define ICMPv6_PARAMPROB_LEN (ICMPv6_COMMON_HEADER_LEN+4) +#define ICMPv6_ECHO_LEN (ICMPv6_COMMON_HEADER_LEN+4) +#define ICMPv6_ECHOREPLY_LEN (ICMPv6_COMMON_HEADER_LEN+4) +#define ICMPv6_ROUTERSOLICIT_LEN (ICMPv6_COMMON_HEADER_LEN+4) +#define ICMPv6_ROUTERADVERT_LEN (ICMPv6_COMMON_HEADER_LEN+12) +#define ICMPv6_NGHBRSOLICIT_LEN (ICMPv6_COMMON_HEADER_LEN+20) +#define ICMPv6_NGHBRADVERT_LEN (ICMPv6_COMMON_HEADER_LEN+20) +#define ICMPv6_REDIRECT_LEN (ICMPv6_COMMON_HEADER_LEN+36) +#define ICMPv6_RTRRENUM_LEN (ICMPv6_COMMON_HEADER_LEN+12) +#define ICMPv6_NODEINFO_LEN (ICMPv6_COMMON_HEADER_LEN+12) +#define ICMPv6_MLD_LEN (ICMPv6_COMMON_HEADER_LEN+20) +/* This must the MAX() of all values defined above*/ +#define ICMPv6_MAX_MESSAGE_BODY (ICMPv6_REDIRECT_LEN-ICMPv6_COMMON_HEADER_LEN) + + + +class ICMPv6Header : public ICMPHeader { + + /**********************************************************************/ + /* COMMON ICMPv6 packet HEADER */ + /**********************************************************************/ + /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + Message Body + + | | */ + struct nping_icmpv6_hdr{ + u8 type; + u8 code; + u16 checksum; + u8 data[ICMPv6_MAX_MESSAGE_BODY]; + }__attribute__((__packed__)); + typedef struct nping_icmpv6_hdr nping_icmpv6_hdr_t; + + + /**********************************************************************/ + /* ICMPv6 MESSAGE SPECIFIC HEADERS */ + /**********************************************************************/ + + /* Destination Unreachable Message + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Unused | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | As much of invoking packet | + + as possible without the ICMPv6 packet + + | exceeding the minimum IPv6 MTU [IPv6] | */ + struct dest_unreach_msg{ + u32 unused; + //u8 invoking_pkt[?]; + }__attribute__((__packed__)); + typedef struct dest_unreach_msg dest_unreach_msg_t; + + + /* Packet Too Big Message + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | MTU | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | As much of invoking packet | + + as possible without the ICMPv6 packet + + | exceeding the minimum IPv6 MTU [IPv6] | */ + struct pkt_too_big_msg{ + u32 mtu; + //u8 invoking_pkt[?]; + }__attribute__((__packed__)); + typedef struct pkt_too_big_msg pkt_too_big_msg_t; + + + /* Time Exceeded Message + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Unused | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | As much of invoking packet | + + as possible without the ICMPv6 packet + + | exceeding the minimum IPv6 MTU [IPv6] | */ + struct time_exceeded_msg{ + u32 unused; + //u8 invoking_pkt[?]; + }__attribute__((__packed__)); + typedef struct time_exceeded_msg time_exceeded_msg_t; + + + /* Parameter Problem Message + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Pointer | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | As much of invoking packet | + + as possible without the ICMPv6 packet + + | exceeding the minimum IPv6 MTU [IPv6] | */ + struct parameter_problem_msg{ + u32 pointer; + //u8 invoking_pkt[?]; + }__attribute__((__packed__)); + typedef struct parameter_problem_msg parameter_problem_msg_t; + + + /* Echo Request/Response Messages + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Identifier | Sequence Number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Data ... + +-+-+-+-+- */ + struct echo_msg{ + u16 id; + u16 seq; + //u8 data[?]; + }__attribute__((__packed__)); + typedef struct echo_msg echo_msg_t; + + /* Router Advertisement Message + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Cur Hop Limit |M|O|H|Prf|P|R|R| Router Lifetime | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Reachable Time | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Retrans Timer | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Options ... + +-+-+-+-+-+-+-+-+-+-+-+- */ + struct router_advert_msg{ + u8 current_hop_limit; + u8 autoconfig_flags; /* See RFC 5175 */ + u16 router_lifetime; + u32 reachable_time; + u32 retransmission_timer; + //u8 icmpv6_options[?]; + }__attribute__((__packed__)); + typedef struct router_advert_msg router_advert_msg_t; + + + /* Router Solicitation Message + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Reserved | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Options ... + +-+-+-+-+-+-+-+-+-+-+-+- */ + struct router_solicit_msg{ + u32 reserved; + //u8 icmpv6_options[?]; + }__attribute__((__packed__)); + typedef struct router_solicit_msg router_solicit_msg_t; + + + /* Neighbor Advertisement Message + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |R|S|O| Reserved | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + + + | | + + Target Address + + | | + + + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Options ... + +-+-+-+-+-+-+-+-+-+-+-+- */ + struct neighbor_advert_msg{ + u8 flags; + u8 reserved[3]; + u8 target_address[16]; + //u8 icmpv6_options[?]; + }__attribute__((__packed__)); + typedef struct neighbor_advert_msg neighbor_advert_msg_t; + + + /* Neighbor Solicitation Message + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Reserved | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + + + | | + + Target Address + + | | + + + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Options ... + +-+-+-+-+-+-+-+-+-+-+-+- */ + struct neighbor_solicit_msg{ + u32 reserved; + u8 target_address[16]; + //u8 icmpv6_options[?]; + }__attribute__((__packed__)); + typedef struct neighbor_solicit_msg neighbor_solicit_msg_t; + + + /* Redirect Message + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Reserved | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + + + | | + + Target Address + + | | + + + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + + + | | + + Destination Address + + | | + + + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Options ... + +-+-+-+-+-+-+-+-+-+-+-+- */ + struct redirect_msg{ + u32 reserved; + u8 target_address[16]; + u8 destination_address[16]; + //u8 icmpv6_options[?]; + }__attribute__((__packed__)); + typedef struct redirect_msg redirect_msg_t; + + + /* Router Renumbering Header + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SequenceNumber | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SegmentNumber | Flags | MaxDelay | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | reserved | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + / RR Message Body / + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + struct router_renumbering_msg{ + u32 seq; + u8 segment_number; + u8 flags; + u16 max_delay; + u32 reserved; + //u8 rr_msg_body[?]; + }__attribute__((__packed__)); + typedef struct router_renumbering_msg router_renumbering_msg_t; + + + /* Node Information Queries + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Qtype | Flags | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + Nonce + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + / Data / + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + struct nodeinfo_msg{ + u16 qtype; + u16 flags; + u8 nonce[NI_NONCE_LEN]; + //u8 data[?]; + }__attribute__((__packed__)); + typedef struct nodeinfo_msg nodeinfo_msg_t; + + + /* Multicast Listener Discovery + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Maximum Response Delay | Reserved | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + + + | | + + Multicast Address + + | | + + + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + struct mld_msg{ + u16 max_response_delay; + u16 reserved; + u8 mcast_address[16]; + }__attribute__((__packed__)); + typedef struct mld_msg mld_msg_t; + + + nping_icmpv6_hdr_t h; + + /* Helper pointers */ + dest_unreach_msg_t *h_du; + pkt_too_big_msg_t *h_ptb; + time_exceeded_msg_t *h_te; + parameter_problem_msg_t *h_pp; + echo_msg_t *h_e; + router_advert_msg_t *h_ra; + router_solicit_msg_t *h_rs; + neighbor_advert_msg_t *h_na; + neighbor_solicit_msg_t *h_ns; + redirect_msg_t *h_r; + router_renumbering_msg_t *h_rr; + nodeinfo_msg_t *h_ni; + mld_msg_t *h_mld; + + public: + ICMPv6Header(); + ~ICMPv6Header(); + void reset(); + u8 *getBufferPointer(); + int storeRecvData(const u8 *buf, size_t len); + int protocol_id() const; + int validate(); + int print(FILE *output, int detail) const; + + /* ICMP Type */ + int setType(u8 val); + u8 getType() const; + bool validateType(); + bool validateType(u8 val); + + /* Code */ + int setCode(u8 c); + u8 getCode() const; + bool validateCode(); + bool validateCode(u8 type, u8 code); + + /* Checksum */ + int setSum(); + int setSum(u16 s); + int setSumRandom(); + u16 getSum(); + + int setReserved(u32 val); + u32 getReserved(); + int setUnused(u32 val); + u32 getUnused(); + + int setFlags(u8 val); + u8 getFlags(); + + int setMTU(u32 mtu); + u32 getMTU(); + + /* Parameter problem */ + int setPointer(u32 val); + u32 getPointer(); + + /* Echo */ + int setIdentifier(u16 val); + u16 getIdentifier(); + int setSequence(u16 val); + int setSequence(u32 val); + u32 getSequence(); + + /* Router Advertisement */ + int setCurrentHopLimit(u8 val); + u8 getCurrentHopLimit(); + + int setRouterLifetime(u16 val); + u16 getRouterLifetime(); + + int setReachableTime(u32 val); + u32 getReachableTime(); + + int setRetransmissionTimer(u32 val); + u32 getRetransmissionTimer(); + + int setTargetAddress(struct in6_addr addr); + struct in6_addr getTargetAddress(); + + int setDestinationAddress(struct in6_addr addr); + struct in6_addr getDestinationAddress(); + + int setSegmentNumber(u8 val); + u8 getSegmentNumber(); + + int setMaxDelay(u16 val); + u16 getMaxDelay(); + + /* Node Information Queries */ + int setQtype(u16 val); + u16 getQtype(); + int setNodeInfoFlags(u16 val); + u16 getNodeInfoFlags(); + int setG(bool flag_value=true); + bool getG(); + int setS(bool flag_value=true); + bool getS(); + int setL(bool flag_value=true); + bool getL(); + int setC(bool flag_value=true); + bool getC(); + int setA(bool flag_value=true); + bool getA(); + int setT(bool flag_value=true); + bool getT(); + int setNonce(const u8 *nonce); + u8 *getNonce(); + + /* Multicast Listener Discovery */ + int setMulticastAddress(struct in6_addr addr); + struct in6_addr getMulticastAddress(); + + /* Misc */ + int getHeaderLengthFromType(u8 type); + bool isError() const; + +}; /* End of class ICMPv6Header */ + +#endif diff --git a/libnetutil/ICMPv6Option.cc b/libnetutil/ICMPv6Option.cc new file mode 100755 index 0000000000..59dc57ef46 --- /dev/null +++ b/libnetutil/ICMPv6Option.cc @@ -0,0 +1,357 @@ + +/*************************************************************************** + * ICMPv6Option.cc -- The ICMPv6Option Class represents an ICMP version 6 * + * option. It contains methods to set any header field. In general, these * + * methods do error checkings and byte order conversion. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#include "ICMPv6Option.h" + + +ICMPv6Option::ICMPv6Option() { + this->reset(); +} /* End of ICMPv6Option constructor */ + + +ICMPv6Option::~ICMPv6Option() { + +} /* End of ICMPv6Option destructor */ + + +/** Sets every class attribute to zero */ +void ICMPv6Option::reset(){ + memset(&this->h, 0, sizeof(nping_icmpv6_option_t)); + h_la = (link_addr_option_t *)this->h.data; + h_pi = (prefix_info_option_t *)this->h.data; + h_r = (redirect_option_t *)this->h.data; + h_mtu = (mtu_option_t *)this->h.data; +} /* End of reset() */ + + +/** @warning This method is essential for the superclass getBinaryBuffer() + * method to work. Do NOT change a thing unless you know what you're doing */ +u8 *ICMPv6Option::getBufferPointer(){ + return (u8*)(&this->h); +} /* End of getBufferPointer() */ + + +/** Stores supplied packet in the internal buffer so the information + * can be accessed using the standard get & set methods. + * @warning The ICMPv6Option class is able to hold a maximum of + * sizeof(nping_icmpv6_option_t) bytes. If the supplied buffer is longer than + * that, only the first sizeof(nping_icmpv6_option_t) bytes will be stored in + * the internal buffer. + * @warning Supplied len MUST be at least ICMPv6_OPTION_MIN_HEADER_LEN bytes + * @return OP_SUCCESS on success and OP_FAILURE in case of error */ +int ICMPv6Option::storeRecvData(const u8 *buf, size_t len){ + if(buf==NULL || lenreset(); /* Re-init the object, just in case the caller had used it already */ + this->length=stored_len; + memcpy(&(this->h), buf, stored_len); + } + return OP_SUCCESS; +} /* End of storeRecvData() */ + +int ICMPv6Option::protocol_id() const { + return HEADER_TYPE_ICMPv6_OPTION; +} + + +int ICMPv6Option::setType(u8 val){ + this->h.type=val; + this->length = getHeaderLengthFromType(val); + this->h.length = this->length / 8; + return OP_SUCCESS; +} /* End of setType() */ + +u8 ICMPv6Option::getType(){ + return this->h.type; +} /* End of getType() */ + + +bool ICMPv6Option::validateType(u8 val){ + switch( val ){ + case ICMPv6_OPTION_SRC_LINK_ADDR: + case ICMPv6_OPTION_TGT_LINK_ADDR: + case ICMPv6_OPTION_PREFIX_INFO: + case ICMPv6_OPTION_REDIR_HDR: + case ICMPv6_OPTION_MTU: + return true; + break; + + default: + return false; + break; + } + return false; +} /* End of validateType() */ + + + +int ICMPv6Option::setLength(u8 val){ + this->h.length=val; + return OP_SUCCESS; +} /* End of setLength() */ + +u8 ICMPv6Option::getLength(){ + return this->h.length; +} /* End of getLength() */ + + +int ICMPv6Option::setLinkAddress(u8* val){ + if(val==NULL) + return OP_FAILURE; + switch(this->h.type){ + case ICMPv6_OPTION_SRC_LINK_ADDR: + case ICMPv6_OPTION_TGT_LINK_ADDR: + memcpy(this->h_la->link_addr, val, ICMPv6_OPTION_LINK_ADDRESS_LEN); + return OP_SUCCESS; + break; + + default: + return OP_FAILURE; + break; + } +} /* End of setLinkAddress() */ + + +u8 *ICMPv6Option::getLinkAddress(){ + switch(this->h.type){ + case ICMPv6_OPTION_SRC_LINK_ADDR: + case ICMPv6_OPTION_TGT_LINK_ADDR: + return this->h_la->link_addr; + break; + + default: + return NULL; + break; + } +} /* End of getLinkAddress() */ + + +int ICMPv6Option::setPrefixLength(u8 val){ + if(this->h.type!=ICMPv6_OPTION_PREFIX_INFO) + return OP_FAILURE; + this->h_pi->prefix_length=val; + return OP_SUCCESS; +} /* End of setPrefixLength() */ + + +u8 ICMPv6Option::getPrefixLength(){ + if(this->h.type!=ICMPv6_OPTION_PREFIX_INFO) + return 0; + else + return this->h_pi->prefix_length; +} /* End of getPrefixLength() */ + + +int ICMPv6Option::setFlags(u8 val){ + if(this->h.type!=ICMPv6_OPTION_PREFIX_INFO) + return OP_FAILURE; + this->h_pi->flags=val; + return OP_SUCCESS; +} /* End of setFlags() */ + + +u8 ICMPv6Option::getFlags(){ + if(this->h.type!=ICMPv6_OPTION_PREFIX_INFO) + return 0; + else + return this->h_pi->flags; +} /* End of getFlags() */ + + +int ICMPv6Option::setValidLifetime(u32 val){ + if(this->h.type!=ICMPv6_OPTION_PREFIX_INFO) + return OP_FAILURE; + this->h_pi->valid_lifetime=htonl(val); + return OP_SUCCESS; +} /* End of setValidLifetime() */ + + +u32 ICMPv6Option::getValidLifetime(){ + if(this->h.type!=ICMPv6_OPTION_PREFIX_INFO) + return 0; + else + return ntohl(this->h_pi->valid_lifetime); +} /* End of getValidLifetime() */ + + +int ICMPv6Option::setPreferredLifetime(u32 val){ + if(this->h.type!=ICMPv6_OPTION_PREFIX_INFO) + return OP_FAILURE; + this->h_pi->preferred_lifetime=htonl(val); + return OP_SUCCESS; +} /* End of setPreferredLifetime() */ + + +u32 ICMPv6Option::getPreferredLifetime(){ + if(this->h.type!=ICMPv6_OPTION_PREFIX_INFO) + return 0; + else + return ntohl(this->h_pi->preferred_lifetime); +} /* End of getPreferredLifetime() */ + + +int ICMPv6Option::setPrefix(u8 *val){ + if(val==NULL || this->h.type!=ICMPv6_OPTION_PREFIX_INFO) + return OP_FAILURE; + else + memcpy(this->h_pi->prefix, val, 16); + return OP_SUCCESS; +} /* End of setPrefix() */ + + +u8 *ICMPv6Option::getPrefix(){ + if(this->h.type!=ICMPv6_OPTION_PREFIX_INFO) + return NULL; + else + return this->h_pi->prefix; +} /* End of getPrefix() */ + + +int ICMPv6Option::setMTU(u32 val){ + if(this->h.type!=ICMPv6_OPTION_MTU) + return OP_FAILURE; + this->h_mtu->mtu=htonl(val); + return OP_SUCCESS; +} /* End of setMTU() */ + + +u32 ICMPv6Option::getMTU(){ + if(this->h.type!=ICMPv6_OPTION_MTU) + return 0; + else + return ntohl(this->h_mtu->mtu); +} /* End of getMTU() */ + + + +/******************************************************************************/ +/* MISCELLANEOUS STUFF */ +/******************************************************************************/ + +/** Returns the standard ICMPv6 optiom length for the supplied option type. + * @warning Return value corresponds strictly to the ICMPv7 option header, this + * is, the minimum length of the OPTION, variable length payload is never + * included. For example, an ICMPv6 Redirect option has a fixed header of 8 + * bytes but then it may contain an IPv6 header. We only return 8 + * because we don't know in advance the total number of bytes for the message. + * Same applies to the rest of types. */ +int ICMPv6Option::getHeaderLengthFromType(u8 type){ + switch( type ){ + case ICMPv6_OPTION_SRC_LINK_ADDR: + return ICMPv6_OPTION_SRC_LINK_ADDR_LEN; + break; + + case ICMPv6_OPTION_TGT_LINK_ADDR: + return ICMPv6_OPTION_TGT_LINK_ADDR_LEN; + break; + + case ICMPv6_OPTION_PREFIX_INFO: + return ICMPv6_OPTION_PREFIX_INFO_LEN; + break; + + case ICMPv6_OPTION_REDIR_HDR: + return ICMPv6_OPTION_REDIR_HDR_LEN; + break; + + case ICMPv6_OPTION_MTU: + return ICMPv6_OPTION_MTU_LEN; + break; + + /* Packets with non RFC-Compliant option types will be represented as an + * 8-byte ICMPv6 option. */ + default: + return ICMPv6_OPTION_MIN_HEADER_LEN; + break; + } +} /* End of getHeaderLengthFromType() */ diff --git a/libnetutil/ICMPv6Option.h b/libnetutil/ICMPv6Option.h new file mode 100755 index 0000000000..a94eed5a6f --- /dev/null +++ b/libnetutil/ICMPv6Option.h @@ -0,0 +1,266 @@ + +/*************************************************************************** + * ICMPv6Option.h -- The ICMPv6Option Class represents an ICMP version 6 * + * option. It contains methods to set any header field. In general, these * + * methods do error checkings and byte order conversion. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#ifndef __ICMPv6OPTION_H__ +#define __ICMPv6OPTION_H__ 1 + +#include "NetworkLayerElement.h" + +/* Packet header diagrams included in this file have been taken from the + * following IETF RFC documents: RFC 2461, RFC 2894 */ + +/* The following codes have been defined by IANA. A complete list may be found + * at http://www.iana.org/assignments/icmpv6-parameters */ + +/* ICMPv6 Option Types */ +#define ICMPv6_OPTION_SRC_LINK_ADDR 1 +#define ICMPv6_OPTION_TGT_LINK_ADDR 2 +#define ICMPv6_OPTION_PREFIX_INFO 3 +#define ICMPv6_OPTION_REDIR_HDR 4 +#define ICMPv6_OPTION_MTU 5 + +/* Nping ICMPv6Options Class internal definitions */ +#define ICMPv6_OPTION_COMMON_HEADER_LEN 2 +#define ICMPv6_OPTION_MIN_HEADER_LEN 8 +#define ICMPv6_OPTION_SRC_LINK_ADDR_LEN (ICMPv6_OPTION_COMMON_HEADER_LEN+6) +#define ICMPv6_OPTION_TGT_LINK_ADDR_LEN (ICMPv6_OPTION_COMMON_HEADER_LEN+6) +#define ICMPv6_OPTION_PREFIX_INFO_LEN (ICMPv6_OPTION_COMMON_HEADER_LEN+30) +#define ICMPv6_OPTION_REDIR_HDR_LEN (ICMPv6_OPTION_COMMON_HEADER_LEN+6) +#define ICMPv6_OPTION_MTU_LEN (ICMPv6_OPTION_COMMON_HEADER_LEN+6) +/* This must the MAX() of all values defined above*/ +#define ICMPv6_OPTION_MAX_MESSAGE_BODY (ICMPv6_OPTION_PREFIX_INFO_LEN-ICMPv6_OPTION_COMMON_HEADER_LEN) + +#define ICMPv6_OPTION_LINK_ADDRESS_LEN 6 + +class ICMPv6Option : public NetworkLayerElement { + + private: + + /**********************************************************************/ + /* COMMON ICMPv6 OPTION HEADER */ + /**********************************************************************/ + + struct nping_icmpv6_option{ + u8 type; + u8 length; + u8 data[ICMPv6_OPTION_MAX_MESSAGE_BODY]; + }__attribute__((__packed__)); + typedef struct nping_icmpv6_option nping_icmpv6_option_t; + + /**********************************************************************/ + /* ICMPv6 OPTION FORMATS */ + /**********************************************************************/ + /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Length | ... | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ~ ... ~ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + + + /* Source/Target Link-layer Address + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Length | Link-Layer Address ... + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + struct link_addr_option{ + u8 link_addr[6]; + }__attribute__((__packed__)); + typedef struct link_addr_option link_addr_option_t; + + + /* Prefix Information + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Length | Prefix Length |L|A| Reserved1 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Valid Lifetime | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Preferred Lifetime | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Reserved2 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + + + | | + + Prefix + + | | + + + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + struct prefix_info_option{ + u8 prefix_length; + u8 flags; + u32 valid_lifetime; + u32 preferred_lifetime; + u32 reserved; + u8 prefix[16]; + }__attribute__((__packed__)); + typedef struct prefix_info_option prefix_info_option_t; + + + /* Redirect Header + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Length | Reserved | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Reserved | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + ~ IP header + data ~ + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + struct redirect_option{ + u16 reserved_1; + u32 reserved_2; + //u8 invoking_pkt[?]; + }__attribute__((__packed__)); + typedef struct redirect_option redirect_option_t; + + + /* MTU + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Length | Reserved | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | MTU | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + struct mtu_option{ + u16 reserved; + u32 mtu; + }__attribute__((__packed__)); + typedef struct mtu_option mtu_option_t; + + + nping_icmpv6_option_t h; + + link_addr_option_t *h_la; + prefix_info_option_t *h_pi; + redirect_option_t *h_r; + mtu_option_t *h_mtu; + + public: + ICMPv6Option(); + ~ICMPv6Option(); + void reset(); + u8 *getBufferPointer(); + int storeRecvData(const u8 *buf, size_t len); + int protocol_id() const; + + int setType(u8 val); + u8 getType(); + bool validateType(u8 val); + + int setLength(u8 val); + u8 getLength(); + + int setLinkAddress(u8* val); + u8 *getLinkAddress(); + + int setPrefixLength(u8 val); + u8 getPrefixLength(); + + int setFlags(u8 val); + u8 getFlags(); + + int setValidLifetime(u32 val); + u32 getValidLifetime(); + + int setPreferredLifetime(u32 val); + u32 getPreferredLifetime(); + + int setPrefix(u8 *val); + u8 *getPrefix(); + + int setMTU(u32 val); + u32 getMTU(); + + int getHeaderLengthFromType(u8 type); + +}; /* End of class ICMPv6Option */ + +#endif diff --git a/libnetutil/ICMPv6RRBody.cc b/libnetutil/ICMPv6RRBody.cc new file mode 100755 index 0000000000..e8a0f20a22 --- /dev/null +++ b/libnetutil/ICMPv6RRBody.cc @@ -0,0 +1,142 @@ + +/*************************************************************************** + * ICMPv6RRBody.h -- The ICMPv6RRBody Class represents an ICMP version 6 * + * Router Renumbering message body. It contains methods to set any header * + * field. In general, these methods do error checkings and byte order * + * conversions. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#include "ICMPv6RRBody.h" + + +ICMPv6RRBody::ICMPv6RRBody() { + this->reset(); +} /* End of ICMPv6RRBody constructor */ + + +ICMPv6RRBody::~ICMPv6RRBody() { + +} /* End of ICMPv6RRBody destructor */ + + +/** Sets every class attribute to zero */ +void ICMPv6RRBody::reset(){ + memset(&this->h, 0, sizeof(nping_icmpv6_rr_body_t)); + h_mp = (rr_match_prefix_t *)this->h.data; + h_up = (rr_use_prefix_t *)this->h.data; + h_r = (rr_result_msg_t *)this->h.data; +} /* End of reset() */ + + +/** @warning This method is essential for the superclass getBinaryBuffer() + * method to work. Do NOT change a thing unless you know what you're doing */ +u8 *ICMPv6RRBody::getBufferPointer(){ + return (u8*)(&this->h); +} /* End of getBufferPointer() */ + + +/** Stores supplied packet in the internal buffer so the information + * can be accessed using the standard get & set methods. + * @warning The ICMPv6RRBody class is able to hold a maximum of + * sizeof(nping_icmpv6_rr_body_t) bytes. If the supplied buffer is longer than + * that, only the first sizeof(nping_icmpv6_rr_body_t) bytes will be stored in + * the internal buffer. + * @warning Supplied len MUST be at least ICMPv6_RR_MIN_LENGTH bytes + * @return OP_SUCCESS on success and OP_FAILURE in case of error */ +int ICMPv6RRBody::storeRecvData(const u8 *buf, size_t len){ + if(buf==NULL || lenreset(); /* Re-init the object, just in case the caller had used it already */ + this->length=stored_len; + memcpy(&(this->h), buf, stored_len); + } + return OP_SUCCESS; +} /* End of storeRecvData() */ + diff --git a/libnetutil/ICMPv6RRBody.h b/libnetutil/ICMPv6RRBody.h new file mode 100755 index 0000000000..79ee247b89 --- /dev/null +++ b/libnetutil/ICMPv6RRBody.h @@ -0,0 +1,231 @@ + +/*************************************************************************** + * ICMPv6RRBody.cc -- The ICMPv6RRBody Class represents an ICMP version 6 * + * Router Renumbering message body. It contains methods to set any header * + * field. In general, these methods do error checkings and byte order * + * conversions. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#ifndef ICMPv6HEADER_H +#define ICMPv6HEADER_H 1 + +#include "NetworkLayerElement.h" + +/* Packet header diagrams included in this file have been taken from the + * following IETF RFC documents: RFC 2894 */ + +/* Nping ICMPv6RRBody Class internal definitions */ +#define ICMPv6_RR_MATCH_PREFIX_LEN 24 +#define ICMPv6_RR_USE_PREFIX_LEN 32 +#define ICMPv6_RR_RESULT_MSG_LEN 24 +/* This must the MAX() of all values defined above*/ +#define ICMPv6_RR_MAX_LENGTH (ICMPv6_RR_USE_PREFIX_LEN) +#define ICMPv6_RR_MIN_LENGTH (ICMPv6_RR_MATCH_PREFIX_LEN) + + +class ICMPv6RRBody : public NetworkLayerElement { + + private: + + /**********************************************************************/ + /* COMMON ICMPv6 OPTION HEADER */ + /**********************************************************************/ + + struct nping_icmpv6_rr_body{ + u8 data[ICMPv6_RR_MAX_LENGTH]; + }__attribute__((__packed__)); + typedef struct nping_icmpv6_rr_body nping_icmpv6_rr_body_t; + + /**********************************************************************/ + /* ICMPv6 OPTION FORMATS */ + /**********************************************************************/ + + + /* Match-Prefix Part + + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | OpCode | OpLength | Ordinal | MatchLen | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | MinLen | MaxLen | reserved | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + +- -+ + | | + +- MatchPrefix -+ + | | + +- -+ + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + struct rr_match_prefix{ + u8 op_code; + u8 op_length; + u8 ordinal; + u8 match_length; + u8 min_length; + u8 max_length; + u16 reserved; + u8 match_prefix[16]; + }__attribute__((__packed__)); + typedef struct rr_match_prefix rr_match_prefix_t; + + + /* Use-Prefix Part + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | UseLen | KeepLen | FlagMask | RAFlags | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Valid Lifetime | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Preferred Lifetime | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |V|P| reserved | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + +- -+ + | | + +- UsePrefix -+ + | | + +- -+ + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + struct rr_use_prefix{ + u8 use_len; + u8 keep_len; + u8 flag_mask; + u8 ra_flags; + u32 valid_lifetime; + u32 preferred_lifetime; + u8 flags; + u8 reserved[3]; + u8 use_prefix[16]; + }__attribute__((__packed__)); + typedef struct rr_use_prefix rr_use_prefix_t; + + + /* Result Message + + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | reserved |B|F| Ordinal | MatchedLen | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | InterfaceIndex | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + +- -+ + | | + +- MatchedPrefix -+ + | | + +- -+ + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + struct rr_result_msg{ + u8 reserved; + u8 flags; + u8 ordinal; + u8 matched_length; + u32 interface_index; + u8 matched_prefix[16]; + }__attribute__((__packed__)); + typedef struct rr_result_msg rr_result_msg_t; + + nping_icmpv6_rr_body_t h; + + rr_match_prefix_t *h_mp; + rr_use_prefix_t *h_up; + rr_result_msg_t *h_r; + + public: + ICMPv6RRBody(); + ~ICMPv6RRBody(); + void reset(); + u8 *getBufferPointer(); + int storeRecvData(const u8 *buf, size_t len); + +}; /* End of class ICMPv6RRBody */ + +#endif diff --git a/libnetutil/IPv4Header.cc b/libnetutil/IPv4Header.cc new file mode 100644 index 0000000000..730bb4fab3 --- /dev/null +++ b/libnetutil/IPv4Header.cc @@ -0,0 +1,654 @@ + +/*************************************************************************** + * IPv4Header.cc -- The IPv4Header Class represents an IPv4 datagram. It * + * contains methods to set any header field. In general, these methods do * + * error checkings and byte order conversion. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#include "IPv4Header.h" + +/******************************************************************************/ +/* CONTRUCTORS, DESTRUCTORS AND INITIALIZATION METHODS */ +/******************************************************************************/ +IPv4Header::IPv4Header() { + this->reset(); +} /* End of IPv4Header constructor */ + + +IPv4Header::~IPv4Header() { + +} /* End of IPv4Header destructor */ + + +/** Sets every attribute to its default value */ +void IPv4Header::reset() { + memset(&this->h, 0, sizeof(nping_ipv4_hdr_t)); + this->ipoptlen=0; + this->length=20; /* Initial value 20. This will be incremented if options are used */ + this->setVersion(); + this->setHeaderLength(); + this->setTOS(IPv4_DEFAULT_TOS); + this->setIdentification(IPv4_DEFAULT_ID); + this->setTTL(IPv4_DEFAULT_TTL); + this->setNextProto(IPv4_DEFAULT_PROTO); + this->setTotalLength(); +} /* End of IPv4Header destructor */ + + +/******************************************************************************/ +/* PacketElement:: OVERWRITTEN METHODS */ +/******************************************************************************/ + +/** @warning This method is essential for the superclass getBinaryBuffer() + * method to work. Do NOT change a thing unless you know what you're doing */ +u8 *IPv4Header::getBufferPointer(){ + return (u8*)(&h); +} /* End of getBufferPointer() */ + +/** Stores supplied packet in the internal buffer so the information + * can be accessed using the standard get & set methods. + * @warning The IPv4Header class is able to hold a maximum of 60 bytes. If the + * supplied buffer is longer than that, only the first 60 bytes will be stored + * in the internal buffer. + * @warning Supplied len MUST be at least 20 bytes (min IP header length). + * @return OP_SUCCESS on success and OP_FAILURE in case of error */ +int IPv4Header::storeRecvData(const u8 *buf, size_t len){ + if(buf==NULL || lenreset(); /* Re-init the object, just in case the caller had used it already */ + this->length=stored_len; + memcpy(&(this->h), buf, stored_len); + } + return OP_SUCCESS; +} /* End of storeRecvData() */ + + +/* Returns a protocol identifier. This is used by packet parsing funtions + * that return linked lists of PacketElement objects, to determine the protocol + * the object represents. */ +int IPv4Header::protocol_id() const { + return HEADER_TYPE_IPv4; +} /* End of protocol_id() */ + + +/** Performs some VERY BASIC checks that intend to validate the information + * stored in the internal buffer, as a valid protocol header. + * @warning If the information stored in the object has been set through a + * call to storeRecvData(), the object's internal length count may be updated + * if the validation is successful. + * @return the length, in bytes, of the header, if its found to be valid or + * OP_FAILURE (-1) otherwise. */ +int IPv4Header::validate(){ + if(this->getVersion()!=4) + return OP_FAILURE; + else if( this->getHeaderLength()<5) + return OP_FAILURE; + else if( this->getHeaderLength()*4 > this->length) + return OP_FAILURE; + this->length=this->getHeaderLength()*4; + return this->length; +} /* End of validate() */ + + +/** Prints the contents of the header and calls print() on the next protocol + * header in the chain (if there is any). + * @return OP_SUCCESS on success and OP_FAILURE in case of error. */ +int IPv4Header::print(FILE *output, int detail) const { + static char ipstring[256]; + memset(ipstring, 0, 256); + struct in_addr addr; + int frag_off = 8 * this->getFragOffset() & 8191; /* 2^13 - 1 */; + char ipinfo[512] = ""; /* Temp info about IP. */ + char fragnfo[64] = ""; /* Temp info about fragmentation. */ + + fprintf(output, "IPv4["); + + this->getSourceAddress(&addr); + inet_ntop(AF_INET, &addr, ipstring, sizeof(ipstring)); + fprintf(output, "%s", ipstring); + + fprintf(output, " >"); + + this->getDestinationAddress(&addr); + inet_ntop(AF_INET, &addr, ipstring, sizeof(ipstring)); + fprintf(output, " %s", ipstring); + + /* Is this a fragmented packet? is it the last fragment? */ + if (frag_off || this->getMF()) { + Snprintf(fragnfo, sizeof(fragnfo), " frag offset=%d%s", frag_off, this->getMF() ? "+" : ""); + } + + /* Create a string with information relevant to the specified level of detail */ + if( detail == PRINT_DETAIL_LOW ){ + Snprintf(ipinfo, sizeof(ipinfo), "ttl=%d id=%d iplen=%d%s%s%s%s", + this->getTTL(), this->getIdentification(), this->getTotalLength(), fragnfo, + this->getHeaderLength()==5?"":" ipopts={", + this->getHeaderLength()?"":format_ip_options(this->h.options , MIN(this->getHeaderLength()*4, this->length-IP_HEADER_LEN)), + this->getHeaderLength()?"":"}"); + }else if( detail == PRINT_DETAIL_MED ){ + Snprintf(ipinfo, sizeof(ipinfo), "ttl=%d id=%d proto=%d csum=0x%04X iplen=%d%s%s%s%s", + this->getTTL(), this->getIdentification(), + this->getNextProto(), this->getSum(), + this->getTotalLength(), fragnfo, + this->getHeaderLength()==5?"":" ipopts={", + this->getHeaderLength()==5?"":format_ip_options(this->h.options , MIN(this->getHeaderLength()*4, this->length-IP_HEADER_LEN)), + this->getHeaderLength()==5?"":"}"); + }else if( detail>=PRINT_DETAIL_HIGH ){ + Snprintf(ipinfo, sizeof(ipinfo), "ver=%d ihl=%d tos=0x%02x iplen=%d id=%d%s%s%s%s foff=%d%s ttl=%d proto=%d csum=0x%04X%s%s%s", + this->getVersion(), this->getHeaderLength(), + this->getTOS(), this->getTotalLength(), + this->getIdentification(), + (this->getRF() ||this->getDF()||this->getMF()) ? " flg=" : "", + (this->getRF()) ? "x" : "", + (this->getDF() )? "D" : "", + (this->getMF() )? "M": "", + frag_off, (this->getMF()) ? "+" : "", + this->getTTL(), this->getNextProto(), + this->getSum(), + this->getHeaderLength()==5?"":" ipopts={", + this->getHeaderLength()==5?"":format_ip_options(this->h.options , MIN(this->getHeaderLength()*4, this->length-IP_HEADER_LEN)), + this->getHeaderLength()==5?"":"}"); + } + + fprintf(output, " %s]", ipinfo); + + if(this->next!=NULL){ + print_separator(output, detail); + next->print(output, detail); + } + return OP_SUCCESS; +} /* End of print() */ + + +/******************************************************************************/ +/* PROTOCOL-SPECIFIC METHODS */ +/******************************************************************************/ + +int IPv4Header::setVersion(){ + h.ip_v = 4; + return 4; +} /* End of setVersion() */ + + +u8 IPv4Header::getVersion() const { + return (u8)h.ip_v; +} /* End of getVersion() */ + + +int IPv4Header::setHeaderLength(){ + h.ip_hl = 5 + (ipoptlen/4); + return OP_SUCCESS; +} /* End of setHeaderLength() */ + + +int IPv4Header::setHeaderLength(u8 l){ + h.ip_hl = l; + return OP_SUCCESS; +} /* End of setHeaderLength() */ + + +u8 IPv4Header::getHeaderLength() const { + return h.ip_hl; +} /* End of getHeaderLength() */ + + +int IPv4Header::setTOS(u8 v){ + h.ip_tos = v; + return OP_SUCCESS; +} /* End of setTOS() */ + + +u8 IPv4Header::getTOS() const { + return h.ip_tos; +} /* End of getTOS() */ + + +int IPv4Header::setTotalLength(){ + int mylen = 4*getHeaderLength(); + int otherslen=0; + + if (next!=NULL) + otherslen=next->getLen(); + h.ip_len=htons( mylen+otherslen ); + return OP_SUCCESS; +} /* End of setTotalLength() */ + + +/** @warning Supplied value MUST be in host byte order because it will get + * converted by this method using htons() */ +int IPv4Header::setTotalLength(u16 l){ + h.ip_len = htons(l); + return OP_SUCCESS; +} /* End of setTotalLength() */ + + +/** @warning Returned value is already in host byte order. */ +u16 IPv4Header::getTotalLength() const { + return ntohs(h.ip_len); +} /* End of getTotalLength() */ + + +/** Sets identification field to a random value */ +int IPv4Header::setIdentification(){ + h.ip_id=get_random_u16(); + return OP_SUCCESS; +} /* End of setIdentification() */ + + +/** @warning Supplied value MUST be in host byte order because it will get + * converted by this method using htons() */ +int IPv4Header::setIdentification(u16 i){ + h.ip_id = htons(i); + return OP_SUCCESS; +} /* End of setIdentification() */ + + +/** @warning Returned value is already in host byte order. */ +u16 IPv4Header::getIdentification() const { + return ntohs(h.ip_id); +} /* End of getIdentification() */ + + +/** Sets fragment offset field to a random value */ +int IPv4Header::setFragOffset(){ + /* TODO: Should we check here that i<8192 ? */ + h.ip_off=get_random_u16(); + return OP_SUCCESS; +} /* End of setFragOffset() */ + + +/** @warning Supplied value MUST be in host byte order because it will get + * converted by this method using htons() */ +int IPv4Header::setFragOffset(u16 i){ + /* TODO: Should we check here that i<8192 ? */ + h.ip_off = htons(i); + return OP_SUCCESS; +} /* End of setFragOffset() */ + + +/** @warning Returned value is already in host byte order. */ +u16 IPv4Header::getFragOffset() const { + return ntohs(h.ip_off); +} /* End of getFragOffset() */ + + +/** Set RF flag */ +int IPv4Header::setRF(){ + h.ip_off |= htons(IP_RF); + return OP_SUCCESS; +} /* End of setRF() */ + +/** Unset RF flag */ +int IPv4Header::unsetRF(){ + h.ip_off ^= htons(IP_RF); + return OP_SUCCESS; +} /* End of unsetRF() */ + + +/** Get RF flag */ +bool IPv4Header::getRF() const { + return h.ip_off & htons(IP_RF); +} /* End of getRF() */ + + +/** Set MF flag */ +int IPv4Header::setMF(){ + h.ip_off |= htons(IP_MF); + return OP_SUCCESS; +} /* End of setMF() */ + + +/** Unset MF flag */ +int IPv4Header::unsetMF(){ + h.ip_off ^= htons(IP_MF); + return OP_SUCCESS; +} /* End of unsetMF() */ + + +/* Get MF flag */ +bool IPv4Header::getMF() const { + return h.ip_off & htons(IP_MF); +} /* End of getMF() */ + + +/** Set DF flag */ +int IPv4Header::setDF(){ + h.ip_off |= htons(IP_DF); + return OP_SUCCESS; +} /* End of setDF() */ + + +/** Unset DF flag */ +int IPv4Header::unsetDF(){ + h.ip_off ^= htons(IP_DF); + return OP_SUCCESS; +} /* End of unsetDF() */ + + +/** Get DF flag */ +bool IPv4Header::getDF() const { + return h.ip_off & htons(IP_DF); +} /* End of getDF) */ + + +/** Sets TTL field to a random value */ +int IPv4Header::setTTL(){ + h.ip_ttl=get_random_u8(); + return OP_SUCCESS; +} /* End of setTTL() */ + + +/** @warning Supplied value MUST be in host byte order because it will get + * converted by this method using htons() */ +int IPv4Header::setTTL(u8 t){ + h.ip_ttl = t; + return OP_SUCCESS; +} /* End of setTTL() */ + + +/** @warning Returned value is already in host byte order. */ +u8 IPv4Header::getTTL() const { + return h.ip_ttl; +} /* End of getTTL() */ + + +/** Sets field "next protocol" to the supplied value. + * @warning: No error checks are made. Make sure the supplied value + * corresponds to an actual IANA number. Check + * http://www.iana.org/assignments/protocol-numbers/ for more details. */ +int IPv4Header::setNextProto(u8 p){ + h.ip_p = p; + return OP_SUCCESS; +} /* End of setNextProto() */ + + +/** Sets field "next protocol" to the number that corresponds to the supplied + * protocol name. Currently onyl TCP, UDP and ICMP are supported. Any + * help to extend this functionality would be appreciated. For a list of all + * proto names and numbers check: + * http://www.iana.org/assignments/protocol-numbers/ */ +int IPv4Header::setNextProto(const char *p){ + if (p==NULL){ + printf("setNextProto(): NULL pointer supplied\n"); + return OP_FAILURE; + } + if( !strcasecmp(p, "TCP") ) + h.ip_p=6; /* 6=IANA number for proto TCP */ + + else if( !strcasecmp(p, "UDP") ) + h.ip_p=17; /* 17=IANA number for proto UDP */ + + else if( !strcasecmp(p, "ICMP") ) + h.ip_p=1; /* 1=IANA number for proto ICMP */ + else{ + printf("setNextProto(): Invalid protocol number\n"); + return OP_FAILURE; + } + return OP_SUCCESS; +} /* End of setNextProto() */ + + +/** Returns next protocol number */ +u8 IPv4Header::getNextProto() const { + return h.ip_p; +} /* End of getNextProto() */ + + +u8 IPv4Header::getNextHeader() const { + return this->getNextProto(); +} /* End of getNextHeader() */ + + +int IPv4Header::setNextHeader(u8 val){ + return this->setNextProto(val); +} /* End of setNextHeader() */ + + +/** Computes the IPv4 header checksum and sets the ip_sum field to the right + * value. */ +int IPv4Header::setSum(){ + h.ip_sum = 0; + /* ip_checksum() comes from libdnet */ + ip_checksum((void*)&h, 20 + ipoptlen ); + return OP_SUCCESS; +} /* End of setSum() */ + + +/** @warning Sum is set to supplied value with NO byte ordering conversion + * performed. + * @warning If sum is supplied this way, no error checks are made. Caller is + * responsible for the correctness of the value. */ +int IPv4Header::setSum(u16 s){ + h.ip_sum = s; + return OP_SUCCESS; +} /* End of setSum() */ + + +/** Set the checksum field to a random value */ +int IPv4Header::setSumRandom(){ + h.ip_sum=get_random_u16(); + return OP_SUCCESS; +} /* End of setRandomSum() */ + + +/** Returns the value of the checksum field. + * @warning The returned value is in NETWORK byte order, no conversion is + * performed */ +u16 IPv4Header::getSum() const { + return h.ip_sum; +} /* End of getSum() */ + + +/** Sets destination IP address. + * @warning Destination IP must be supplied in NETWORK byte order. Usually + * all regular library functions return IPs in network byte order so there + * should be no need to worry. */ +int IPv4Header::setDestinationAddress(u32 d){ + h.ip_dst.s_addr = d; + return OP_SUCCESS; +} /* End of getDestinationAddress() */ + +/** Sets destination IP address. + * @warning Destination IP must be supplied in NETWORK byte order. Usually + * all regular library functions return IPs in network byte order so there + * should be no need to worry. */ +int IPv4Header::setDestinationAddress(struct in_addr d){ + h.ip_dst=d; + return OP_SUCCESS; +} /* End of getDestinationAddress() */ + + +/** Returns destination IP address. + * @warning Returned value is in NETWORK byte order. */ +const u8 *IPv4Header::getDestinationAddress() const { + return (u8 *)(&h.ip_dst.s_addr); +} /* End of getDestinationAddress() */ + + +/** Returns destination IP address. + * @warning Returned value is in NETWORK byte order. */ +struct in_addr IPv4Header::getDestinationAddress(struct in_addr *result) const { + if(result!=NULL) + *result=this->h.ip_dst; + return h.ip_dst; +} /* End of getDestinationAddress() */ + + +/** Sets source IP address. + * @warning Destination IP must be supplied in NETWORK byte order. Usually + * all regular library functions return IPs in network byte order so there + * should be no need to worry. */ +int IPv4Header::setSourceAddress(u32 d){ + h.ip_src.s_addr = d; + return OP_SUCCESS; +} /* End of setSourceAddress() */ + + +/** Sets source IP address. + * @warning Destination IP must be supplied in NETWORK byte order. Usually + * all regular library functions return IPs in network byte order so there + * should be no need to worry. */ +int IPv4Header::setSourceAddress(struct in_addr d){ + h.ip_src=d; + return OP_SUCCESS; +} /* End of setSourceAddress() */ + + +/** Returns source ip + * @warning Returned value is in NETWORK byte order. */ +const u8 *IPv4Header::getSourceAddress() const { + return (u8 *)(&h.ip_src.s_addr); +} /* End of getSourceAddress() */ + + +/** Returns source ip + * @warning Returned value is in NETWORK byte order. */ +struct in_addr IPv4Header::getSourceAddress(struct in_addr *result) const { + if(result!=NULL) + *result=this->h.ip_src; + return h.ip_src; +} /* End of getSourceAddress() */ + + +/** Returns the length of an IPv4 address. */ +u16 IPv4Header::getAddressLength() const { + return 4; +} /* End of getAddressLength()*/ + + +int IPv4Header::setOpts(const char *txt){ + int foo=0; + int bar=0; + int ret=0; + u8 buffer[128]; + char errstr[256]; + + if(txt==NULL){ + printf("setOpts(): NULL pointer supplied.\n"); + return OP_FAILURE; + } + + /* Parse IP options */ + if((ret=parse_ip_options(txt, buffer, 128, &foo, &bar, errstr, sizeof(errstr)))==OP_FAILURE){ + printf("%s\n", errstr); + return OP_FAILURE; + }else{ + /* Copy options to our IP header */ + memcpy(h.options, buffer, ret); + this->ipoptlen=ret; + this->length += ret; + this->setHeaderLength(); + } + return OP_SUCCESS; +} /* End of setOpts() */ + + +const u8 *IPv4Header::getOpts() const { + return h.options; +} /* End of getOpts() */ + + +const u8 *IPv4Header::getOpts(int *len) const { + if(len==NULL) + printf("getOpts(): NULL pointer supplied.\n"); + *len=ipoptlen; + return h.options; +} /* End of getOpts() */ + + +int IPv4Header::printOptions() const { + char *p=format_ip_options(this->h.options, this->ipoptlen); + printf("%s", p); + return OP_SUCCESS; +} /* End of printOptions() */ + +const char *IPv4Header::getOptionsString() const { + return format_ip_options(this->h.options, this->ipoptlen); +} /* End of getOptionsString() */ diff --git a/libnetutil/IPv4Header.h b/libnetutil/IPv4Header.h new file mode 100644 index 0000000000..ed19753da6 --- /dev/null +++ b/libnetutil/IPv4Header.h @@ -0,0 +1,250 @@ + +/*************************************************************************** + * IPv4Header.h -- The IPv4Header Class represents an IPv4 datagram. It * + * contains methods to set any header field. In general, these methods do * + * error checkings and byte order conversion. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#ifndef IPV4HEADER_H +#define IPV4HEADER_H 1 + +#include "NetworkLayerElement.h" + +#define IP_RF 0x8000 /* Reserved fragment flag */ +#define IP_DF 0x4000 /* Dont fragment flag */ +#define IP_MF 0x2000 /* More fragments flag */ +#define IP_OFFMASK 0x1fff /* Mask for fragmenting bits */ +#define IP_HEADER_LEN 20 /* Length of the standard header */ +#define MAX_IP_OPTIONS_LEN 40 /* Max Length for IP Options */ + +/* Default header values */ +#define IPv4_DEFAULT_TOS 0 +#define IPv4_DEFAULT_ID 0 +#define IPv4_DEFAULT_TTL 64 +#define IPv4_DEFAULT_PROTO 6 /* TCP */ + +class IPv4Header : public NetworkLayerElement { + + private: + /* + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |Version| IHL |Type of Service| Total Length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Identification |Flags| Fragment Offset | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Time to Live | Protocol | Header Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Source Address | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Destination Address | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Options | Padding | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + struct nping_ipv4_hdr { + #if WORDS_BIGENDIAN + u8 ip_v:4; /* Version */ + u8 ip_hl:4; /* Header length */ + #else + u8 ip_hl:4; /* Header length */ + u8 ip_v:4; /* Version */ + #endif + u8 ip_tos; /* Type of service */ + u16 ip_len; /* Total length */ + u16 ip_id; /* Identification */ + u16 ip_off; /* Fragment offset field */ + u8 ip_ttl; /* Time to live */ + u8 ip_p; /* Protocol */ + u16 ip_sum; /* Checksum */ + struct in_addr ip_src; /* Source IP address */ + struct in_addr ip_dst; /* Destination IP address */ + u8 options[MAX_IP_OPTIONS_LEN]; /* IP Options */ + }__attribute__((__packed__)); + + typedef struct nping_ipv4_hdr nping_ipv4_hdr_t; + + nping_ipv4_hdr_t h; + + int ipoptlen; /**< Length of IP options */ + + public: + + /* Misc */ + IPv4Header(); + ~IPv4Header(); + void reset(); + u8 *getBufferPointer(); + int storeRecvData(const u8 *buf, size_t len); + int protocol_id() const; + int validate(); + int print(FILE *output, int detail) const; + + /* IP version */ + int setVersion(); + u8 getVersion() const; + + /* Header Length */ + int setHeaderLength(); + int setHeaderLength(u8 l); + u8 getHeaderLength() const; + + /* Type of Service */ + int setTOS(u8 v); + u8 getTOS() const; + + /* Total lenght of the datagram */ + int setTotalLength(); + int setTotalLength(u16 l); + u16 getTotalLength() const; + + /* Identification value */ + int setIdentification(); + int setIdentification(u16 i); + u16 getIdentification() const; + + /* Fragment Offset */ + int setFragOffset(); + int setFragOffset(u16 f); + u16 getFragOffset() const; + + /* Flags */ + int setRF(); + int unsetRF(); + bool getRF() const; + int setDF(); + int unsetDF(); + bool getDF() const; + int setMF(); + int unsetMF(); + bool getMF() const; + + /* Time to live */ + int setTTL(); + int setTTL(u8 t); + u8 getTTL() const; + + /* Next protocol */ + int setNextProto(u8 p); + int setNextProto(const char *p); + u8 getNextProto() const; + int setNextHeader(u8 val); + u8 getNextHeader() const; + + /* Checksum */ + int setSum(); + int setSum(u16 s); + int setSumRandom(); + u16 getSum() const; + + /* Destination IP */ + int setDestinationAddress(u32 d); + int setDestinationAddress(struct in_addr d); + const u8 *getDestinationAddress() const; + struct in_addr getDestinationAddress(struct in_addr *result) const; + + + /* Source IP */ + int setSourceAddress(u32 d); + int setSourceAddress(struct in_addr d); + const u8 *getSourceAddress() const; + struct in_addr getSourceAddress(struct in_addr *result) const; + + u16 getAddressLength() const; + + /* IP Options */ + int setOpts(const char *txt); + const u8 *getOpts() const; + const u8 *getOpts(int *len) const; + int printOptions() const; + const char *getOptionsString() const; + +}; /* End of class IPv4Header */ + +#endif diff --git a/libnetutil/IPv6ExtensionHeader.h b/libnetutil/IPv6ExtensionHeader.h new file mode 100644 index 0000000000..129837d9eb --- /dev/null +++ b/libnetutil/IPv6ExtensionHeader.h @@ -0,0 +1,112 @@ + +/*************************************************************************** + * IPv6ExtensionHeader.h -- The IPv6ExtensionHeader class represents * + * a generic class for IPv6 extension headers. Specific headers (like * + * Hop-by-Hop or Routing) inherit from this class. * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#ifndef __IPv6_EXTENSION_HEADER_H__ +#define __IPv6_EXTENSION_HEADER_H__ 1 + +#include "PacketElement.h" + +/* Extension header option codes */ +#define EXTOPT_PAD1 0x00 /* Pad1 (RFC 2460) */ +#define EXTOPT_PADN 0x01 /* PadN (RFC 2460) */ +#define EXTOPT_JUMBO 0xC2 /* Jumbo Payload (RFC 2675) */ +#define EXTOPT_TUNENCAPLIM 0x04 /* Tunnel Encapsulation Limit (RFC 2473) */ +#define EXTOPT_ROUTERALERT 0x05 /* Router Alert (RFC 2711) */ +#define EXTOPT_QUICKSTART 0x26 /* Quick-Start (RFC 4782) */ +#define EXTOPT_CALIPSO 0x07 /* CALIPSO (RFC 5570) */ +#define EXTOPT_HOMEADDR 0xC9 /* Home Address (RFC 6275) */ + +class IPv6ExtensionHeader : public PacketElement { + +}; + +#endif + diff --git a/libnetutil/IPv6Header.cc b/libnetutil/IPv6Header.cc new file mode 100755 index 0000000000..8709e481c4 --- /dev/null +++ b/libnetutil/IPv6Header.cc @@ -0,0 +1,511 @@ + +/*************************************************************************** + * IPv6Header.cc -- The IPv6Header Class represents an IPv4 datagram. It * + * contains methods to set any header field. In general, these methods do * + * error checkings and byte order conversion. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#include "IPv6Header.h" + +/******************************************************************************/ +/* CONTRUCTORS, DESTRUCTORS AND INITIALIZATION METHODS */ +/******************************************************************************/ +IPv6Header::IPv6Header() { + this->reset(); +} /* End of IPv6Header constructor */ + + +IPv6Header::~IPv6Header() { + +} /* End of IPv6Header destructor */ + + +/** Sets every attribute to its default value */ +void IPv6Header::reset(){ + memset(&this->h, 0, sizeof(nping_ipv6_hdr_t)); + this->length=IPv6_HEADER_LEN; + this->setVersion(); + this->setTrafficClass(IPv6_DEFAULT_TCLASS); + this->setFlowLabel(IPv6_DEFAULT_FLABEL); + this->setHopLimit(IPv6_DEFAULT_HOPLIM); + this->setNextHeader(IPv6_DEFAULT_NXTHDR); /* No next header */ + this->setPayloadLength(0); +} /* End of reset() */ + + +/******************************************************************************/ +/* PacketElement:: OVERWRITTEN METHODS */ +/******************************************************************************/ + +/** @warning This method is essential for the superclass getBinaryBuffer() + * method to work. Do NOT change a thing unless you know what you're doing */ +u8 *IPv6Header::getBufferPointer(){ + return (u8*)(&h); +} /* End of getBufferPointer() */ + + +/** Stores supplied packet in the internal buffer so the information + * can be accessed using the standard get & set methods. + * @warning The IPv6Header class is able to hold a maximum of 40 bytes. If the + * supplied buffer is longer than that, only the first 40 bytes will be stored + * in the internal buffer. + * @warning Supplied len MUST be at least 40 bytes (IPv6 header length). + * @return OP_SUCCESS on success and OP_FAILURE in case of error */ +int IPv6Header::storeRecvData(const u8 *buf, size_t len){ + if(buf==NULL || lenreset(); /* Re-init the object, just in case the caller had used it already */ + this->length=IPv6_HEADER_LEN; + memcpy(&(this->h), buf, IPv6_HEADER_LEN); + } + return OP_SUCCESS; +} /* End of storeRecvData() */ + + +/* Returns a protocol identifier. This is used by packet parsing funtions + * that return linked lists of PacketElement objects, to determine the protocol + * the object represents. */ +int IPv6Header::protocol_id() const { + return HEADER_TYPE_IPv6; +} /* End of protocol_id() */ + + +/** Determines if the data stored in the object after an storeRecvData() call + * is valid and safe to use. This mainly checks the length of the data but may + * also test the value of certain protocol fields to ensure their correctness. + * @return the length, in bytes, of the header, if its found to be valid or + * OP_FAILURE (-1) otherwise. */ +int IPv6Header::validate(){ + if( this->length!=IPv6_HEADER_LEN) + return OP_FAILURE; + else + return IPv6_HEADER_LEN; +} /* End of validate() */ + + +/** Prints the contents of the header and calls print() on the next protocol + * header in the chain (if there is any). + * @return OP_SUCCESS on success and OP_FAILURE in case of error. */ +int IPv6Header::print(FILE *output, int detail) const { + fprintf(output, "IPv6[]"); + if(this->next!=NULL){ + print_separator(output, detail); + next->print(output, detail); + } + return OP_SUCCESS; +} /* End of print() */ + + +/******************************************************************************/ +/* PROTOCOL-SPECIFIC METHODS */ +/******************************************************************************/ + +/** Set Version field (4 bits). */ +int IPv6Header::setVersion(u8 val){ + union{ + struct firstbyte{ + #if WORDS_BIGENDIAN + u8 ver:4; + u8 tclass:4; + #else + u8 tclass:4; + u8 ver:4; + #endif + }halfbyte; + u8 fullbyte; + }header1stbyte; + + header1stbyte.fullbyte = h.ip6_start[0]; + header1stbyte.halfbyte.ver=val; + h.ip6_start[0]=header1stbyte.fullbyte; + return OP_SUCCESS; +} /* End of setVersion() */ + + +/** Set Version field to value 6. */ +int IPv6Header::setVersion(){ + this->setVersion(6); + return OP_SUCCESS; +} /* End of setVersion() */ + + +/** Returns an 8bit number containing the value of the Version field. */ +u8 IPv6Header::getVersion() const { + union{ + struct firstbyte{ + #if WORDS_BIGENDIAN + u8 ver:4; + u8 tclass:4; + #else + u8 tclass:4; + u8 ver:4; + #endif + }halfbyte; + u8 fullbyte; + }header1stbyte; + + header1stbyte.fullbyte = h.ip6_start[0]; + return (u8)header1stbyte.halfbyte.ver; +} /* End of getVersion() */ + + +int IPv6Header::setTrafficClass(u8 val){ + union{ + struct firstbyte{ + #if WORDS_BIGENDIAN + u8 ver:4; + u8 tclass1:4; + #else + u8 tclass1:4; + u8 ver:4; + #endif + }halfbyte; + u8 fullbyte; + }header1stbyte; + union{ + struct firstbyte{ + #if WORDS_BIGENDIAN + u8 tclass2:4; + u8 flow:4; + #else + u8 flow:4; + u8 tclass2:4; + #endif + }halfbyte; + u8 fullbyte; + }header2ndbyte; + + /* Store old contents */ + header1stbyte.fullbyte = h.ip6_start[0]; + header2ndbyte.fullbyte = h.ip6_start[1]; + + /* Fill the two 4bit halves */ + header1stbyte.halfbyte.tclass1=val>>4; + header2ndbyte.halfbyte.tclass2=val; + + /* Write the bytes back to the header */ + h.ip6_start[0]=header1stbyte.fullbyte; + h.ip6_start[1]=header2ndbyte.fullbyte; + + return OP_SUCCESS; +} /* End of setTrafficClass() */ + + +u8 IPv6Header::getTrafficClass() const { + union{ + struct firstbyte{ + #if WORDS_BIGENDIAN + u8 ver:4; + u8 tclass1:4; + #else + u8 tclass1:4; + u8 ver:4; + #endif + }halfbyte; + u8 fullbyte; + }header1stbyte; + union{ + struct firstbyte{ + #if WORDS_BIGENDIAN + u8 tclass2:4; + u8 flow:4; + #else + u8 flow:4; + u8 tclass2:4; + #endif + }halfbyte; + u8 fullbyte; + }header2ndbyte; + union{ + struct firstbyte{ + #if WORDS_BIGENDIAN + u8 tclass1:4; + u8 tclass2:4; + #else + u8 tclass2:4; + u8 tclass1:4; + #endif + }halfbyte; + u8 fullbyte; + }finalbyte; + + header1stbyte.fullbyte = h.ip6_start[0]; + header2ndbyte.fullbyte = h.ip6_start[1]; + finalbyte.halfbyte.tclass1=header1stbyte.halfbyte.tclass1; + finalbyte.halfbyte.tclass2=header2ndbyte.halfbyte.tclass2; + return finalbyte.fullbyte; +} /* End of getTrafficClass() */ + + +int IPv6Header::setFlowLabel(u32 val){ + u32 netbyte = htonl(val); + u8 *pnt=(u8*)&netbyte; + union{ + struct firstbyte{ + #if WORDS_BIGENDIAN + u8 tclass2:4; + u8 flow:4; + #else + u8 flow:4; + u8 tclass2:4; + #endif + }halfbyte; + u8 fullbyte; + }header2ndbyte; + + header2ndbyte.fullbyte = h.ip6_start[1]; + header2ndbyte.halfbyte.flow=pnt[1]; + h.ip6_start[1]=header2ndbyte.fullbyte; + h.ip6_start[2]=pnt[2]; + h.ip6_start[3]=pnt[3]; + return OP_SUCCESS; +} /* End of setFlowLabel() */ + + +u32 IPv6Header::getFlowLabel() const { + u32 hostbyte=0; + u8 *pnt=(u8*)&hostbyte; + union{ + struct firstbyte{ + #if WORDS_BIGENDIAN + u8 tclass2:4; + u8 flow:4; + #else + u8 flow:4; + u8 tclass2:4; + #endif + }halfbyte; + u8 fullbyte; + }header2ndbyte; + + header2ndbyte.fullbyte = h.ip6_start[1]; + pnt[0]=0; + pnt[1]=header2ndbyte.halfbyte.flow; + pnt[2]=h.ip6_start[2]; + pnt[3]=h.ip6_start[3]; + hostbyte=ntohl(hostbyte); + return hostbyte; +} /* End of getFlowLabel() */ + + +int IPv6Header::setPayloadLength(u16 val){ + this->h.ip6_len = htons(val); + return OP_SUCCESS; +} /* End of setPayloadLength() */ + + +int IPv6Header::setPayloadLength(){ + int otherslen=0; + if (next!=NULL) + otherslen=next->getLen(); + setPayloadLength( otherslen ); + return OP_SUCCESS; +} /* End of setTotalLength() */ + + +u16 IPv6Header::getPayloadLength() const { + return ntohs(this->h.ip6_len); +} /* End of getPayloadLength() */ + + +int IPv6Header::setNextHeader(u8 val){ + this->h.ip6_nh = val; + return OP_SUCCESS; +} /* End of setNextHeader() */ + + +u8 IPv6Header::getNextHeader() const { + return this->h.ip6_nh; +} /* End of getNextHeader() */ + + +/** Sets field "next header" to the number that corresponds to the supplied + * protocol name. Currently onyl TCP, UDP and ICMP are supported. Any + * help to extend this functionality would be appreciated. For a list of all + * proto names and numbers check: + * http://www.iana.org/assignments/protocol-numbers/ */ +int IPv6Header::setNextHeader(const char *p){ + + if (p==NULL){ + printf("setNextProto(): NULL pointer supplied\n"); + return OP_FAILURE; + } + if( !strcasecmp(p, "TCP") ) + setNextHeader(6); /* 6=IANA number for proto TCP */ + else if( !strcasecmp(p, "UDP") ) + setNextHeader(17); /* 17=IANA number for proto UDP */ + else if( !strcasecmp(p, "ICMPv6")) + setNextHeader(58); /* 58=IANA number for proto ICMPv6 */ + else + netutil_fatal("setNextProto(): Invalid protocol number\n"); + return OP_SUCCESS; +} /* End of setNextHeader() */ + + +int IPv6Header::setHopLimit(u8 val){ + this->h.ip6_hopl = val; + return OP_SUCCESS; +} /* End of setHopLimit() */ + + +u8 IPv6Header::getHopLimit() const { + return this->h.ip6_hopl; +} /* End of getHopLimit() */ + + +int IPv6Header::setSourceAddress(u8 *val){ + if(val==NULL) + netutil_fatal("setSourceAddress(): NULL value supplied."); + memcpy(this->h.ip6_src, val, 16); + return OP_SUCCESS; +} /* End of setSourceAddress() */ + + +int IPv6Header::setSourceAddress(struct in6_addr val){ + memcpy(this->h.ip6_src, val.s6_addr, 16); + return OP_SUCCESS; +} /* End of setSourceAddress() */ + + +const u8 *IPv6Header::getSourceAddress() const { + return this->h.ip6_src; +} /* End of getSourceAddress() */ + + +/** Returns source IPv6 address + * @warning Returned value is in NETWORK byte order. */ +struct in6_addr IPv6Header::getSourceAddress(struct in6_addr *result) const { + struct in6_addr myaddr; + memset(&myaddr, 0, sizeof(myaddr)); + memcpy(myaddr.s6_addr, this->h.ip6_src, 16); + + if(result!=NULL) + *result=myaddr; + return myaddr; +} /* End of getSourceAddress() */ + + +int IPv6Header::setDestinationAddress(u8 *val){ + if(val==NULL) + netutil_fatal("setDestinationAddress(): NULL value supplied."); + memcpy(this->h.ip6_dst, val, 16); + return OP_SUCCESS; +} /* End of setDestinationAddress() */ + + +int IPv6Header::setDestinationAddress(struct in6_addr val){ + memcpy(this->h.ip6_dst, val.s6_addr, 16); + return OP_SUCCESS; +} /* End of setDestinationAddress() */ + + +/** Returns destination IPv6 address. */ +const u8 *IPv6Header::getDestinationAddress() const { + return this->h.ip6_dst; +} /* End of getDestinationAddress() */ + + +/** Returns destination IPv6 address + * @warning Returned value is in NETWORK byte order. */ +struct in6_addr IPv6Header::getDestinationAddress(struct in6_addr *result) const { + struct in6_addr myaddr; + memset(&myaddr, 0, sizeof(myaddr)); + memcpy(myaddr.s6_addr, this->h.ip6_dst, 16); + + if(result!=NULL) + *result=myaddr; + return myaddr; +} /* End of getDestinationAddress() */ + + +/** Returns the length of an IPv4 address. */ +u16 IPv6Header::getAddressLength() const { + return 16; +} /* End of getAddressLength()*/ + diff --git a/libnetutil/IPv6Header.h b/libnetutil/IPv6Header.h new file mode 100644 index 0000000000..f18d287d9f --- /dev/null +++ b/libnetutil/IPv6Header.h @@ -0,0 +1,203 @@ + +/*************************************************************************** + * IPv6Header.h -- The IPv6Header Class represents an IPv6 datagram. It * + * contains methods to set any header field. In general, these methods do * + * error checkings and byte order conversion. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#ifndef IPV6HEADER_H +#define IPV6HEADER_H 1 + +#include "NetworkLayerElement.h" + +#define IPv6_HEADER_LEN 40 + +/* Default header values */ +#define IPv6_DEFAULT_TCLASS 0 +#define IPv6_DEFAULT_FLABEL 0 +#define IPv6_DEFAULT_HOPLIM 64 +#define IPv6_DEFAULT_NXTHDR 6 /* TCP */ + +class IPv6Header : public NetworkLayerElement { + + private: + + /* IPv6 Header Format: + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |Version| Traffic Class | Flow Label | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Payload Length | Next Header | Hop Limit | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + +-- --+ + | | + +-- Source Address --+ + | | + +-- --+ + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + +-- --+ + | | + +-- Destination Address --+ + | | + +-- --+ + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + + struct nping_ipv6_hdr { + u8 ip6_start[4]; /* Version, Traffic and Flow */ + u16 ip6_len; /* Payload length */ + u8 ip6_nh; /* Next Header */ + u8 ip6_hopl; /* Hop Limit */ + u8 ip6_src[16]; /* Source IP Address */ + u8 ip6_dst[16]; /* Destination IP Address */ + }__attribute__((__packed__)); + + typedef struct nping_ipv6_hdr nping_ipv6_hdr_t; + + nping_ipv6_hdr_t h; + + public: + + /* Misc */ + IPv6Header(); + ~IPv6Header(); + void reset(); + u8 *getBufferPointer(); + int storeRecvData(const u8 *buf, size_t len); + int protocol_id() const; + int validate(); + int print(FILE *output, int detail) const; + + /* IP version */ + int setVersion(); + int setVersion(u8 val); + u8 getVersion() const; + + /* Traffic class */ + int setTrafficClass(u8 val); + u8 getTrafficClass() const; + + /* Flow Label */ + int setFlowLabel(u32 val); + u32 getFlowLabel() const; + + /* Payload Length */ + int setPayloadLength(u16 val); + int setPayloadLength(); + u16 getPayloadLength() const; + + /* Next Header */ + int setNextHeader(u8 val); + int setNextHeader(const char *p); + u8 getNextHeader() const; + + /* Hop Limit */ + int setHopLimit(u8 val); + u8 getHopLimit() const; + + /* Source Address */ + int setSourceAddress(u8 *val); + int setSourceAddress(struct in6_addr val); + const u8 *getSourceAddress() const; + struct in6_addr getSourceAddress(struct in6_addr *result) const; + + /* Destination Address*/ + int setDestinationAddress(u8 *val); + int setDestinationAddress(struct in6_addr val); + const u8 *getDestinationAddress() const; + struct in6_addr getDestinationAddress(struct in6_addr *result) const; + + u16 getAddressLength() const; +}; + +#endif diff --git a/libnetutil/Makefile.in b/libnetutil/Makefile.in index d54cb66764..8a202d10fb 100644 --- a/libnetutil/Makefile.in +++ b/libnetutil/Makefile.in @@ -14,8 +14,8 @@ LIBPCAPDIR = @libpcapdir@ TARGET = libnetutil.a -SRCS = $(srcdir)/netutil.cc -OBJS = netutil.o +SRCS = $(srcdir)/netutil.cc $(srcdir)/PacketElement.cc $(srcdir)/NetworkLayerElement.cc $(srcdir)/ARPHeader.cc $(srcdir)/PacketElement.cc $(srcdir)/NetworkLayerElement.cc $(srcdir)/TransportLayerElement.cc $(srcdir)/ARPHeader.cc $(srcdir)/EthernetHeader.cc $(srcdir)/ICMPv4Header.cc $(srcdir)/ICMPv6Header.cc $(srcdir)/IPv4Header.cc $(srcdir)/IPv6Header.cc $(srcdir)/TCPHeader.cc $(srcdir)/UDPHeader.cc $(srcdir)/RawData.cc $(srcdir)/HopByHopHeader.cc $(srcdir)/DestOptsHeader.cc $(srcdir)/FragmentHeader.cc $(srcdir)/RoutingHeader.cc $(srcdir)/PacketParser.cc $(srcdir)/npacket.cc +OBJS = netutil.o PacketElement.o NetworkLayerElement.o TransportLayerElement.o ARPHeader.o EthernetHeader.o ICMPv4Header.o ICMPv6Header.o IPv4Header.o IPv6Header.o TCPHeader.o UDPHeader.o RawData.o HopByHopHeader.o DestOptsHeader.o FragmentHeader.o RoutingHeader.o PacketParser.o npacket.o all: $(TARGET) diff --git a/libnetutil/NetworkLayerElement.cc b/libnetutil/NetworkLayerElement.cc new file mode 100644 index 0000000000..2d439ae41c --- /dev/null +++ b/libnetutil/NetworkLayerElement.cc @@ -0,0 +1,93 @@ + +/*************************************************************************** + * NetworkLayerElement.cc -- Class NetworkLayerElement is a generic class * + * that represents a network layer protocol header. Classes like IPv4Header* + * or IPv6Header inherit from it. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#include "NetworkLayerElement.h" diff --git a/libnetutil/NetworkLayerElement.h b/libnetutil/NetworkLayerElement.h new file mode 100644 index 0000000000..074ae3d9e0 --- /dev/null +++ b/libnetutil/NetworkLayerElement.h @@ -0,0 +1,123 @@ + +/*************************************************************************** + * NetworkLayerElement.h -- Class NetworkLayerElement is a generic class * + * that represents a network layer protocol header. Classes like IPv4Header* + * or IPv6Header inherit from it. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#ifndef NETWORKLAYERELEMENT_H +#define NETWORKLAYERELEMENT_H 1 + +#include "PacketElement.h" + +/// class NetworkLayerElement - +class NetworkLayerElement : public PacketElement { + + public: + virtual u16 getAddressLength(){ + return 0; + } + + virtual u8 *getSourceAddress(){ + return NULL; + } + + virtual u8 *getDestinationAddress(){ + return NULL; + } + + virtual int setNextHeader(u8 val){ + return 0; + } + + virtual u8 getNextHeader(){ + return 0; + } +}; + +#endif diff --git a/libnetutil/PacketElement.cc b/libnetutil/PacketElement.cc new file mode 100644 index 0000000000..056ab2ead1 --- /dev/null +++ b/libnetutil/PacketElement.cc @@ -0,0 +1,101 @@ + +/*************************************************************************** + * PacketElement.cc -- The PacketElement Class is a generic class that * + * represents a protocol header or a part of a network packet. Many other * + * classes inherit from it (NetworkLayerElement, TransportLayerElement, * + * etc). * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#include "PacketElement.h" + +PacketElement::PacketElement(){ + next=NULL; /* It's very important these get initialized to NULL */ + prev=NULL; + length=0; +} /* End of PacketElement constructor */ + diff --git a/libnetutil/PacketElement.h b/libnetutil/PacketElement.h new file mode 100644 index 0000000000..6bb4c465d6 --- /dev/null +++ b/libnetutil/PacketElement.h @@ -0,0 +1,299 @@ + +/*************************************************************************** + * PacketElement.h -- The PacketElement Class is a generic class that * + * represents a protocol header or a part of a network packet. Many other * + * classes inherit from it (NetworkLayerElement, TransportLayerElement, * + * etc). * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#ifndef PACKETELEMENT_H +#define PACKETELEMENT_H 1 + +#include "nbase.h" +#include "netutil.h" + +#define HEADER_TYPE_IPv6_HOPOPT 0 /* IPv6 Hop-by-Hop Option */ +#define HEADER_TYPE_ICMPv4 1 /* ICMP Internet Control Message */ +#define HEADER_TYPE_IGMP 2 /* IGMP Internet Group Management */ +#define HEADER_TYPE_IPv4 4 /* IPv4 IPv4 encapsulation */ +#define HEADER_TYPE_TCP 6 /* TCP Transmission Control */ +#define HEADER_TYPE_EGP 8 /* EGP Exterior Gateway Protocol */ +#define HEADER_TYPE_UDP 17 /* UDP User Datagram */ +#define HEADER_TYPE_IPv6 41 /* IPv6 IPv6 encapsulation */ +#define HEADER_TYPE_IPv6_ROUTE 43 /* IPv6-Route Routing Header for IPv6 */ +#define HEADER_TYPE_IPv6_FRAG 44 /* IPv6-Frag Fragment Header for IPv6 */ +#define HEADER_TYPE_GRE 47 /* GRE General Routing Encapsulation */ +#define HEADER_TYPE_ESP 50 /* ESP Encap Security Payload */ +#define HEADER_TYPE_AH 51 /* AH Authentication Header */ +#define HEADER_TYPE_ICMPv6 58 /* IPv6-ICMP ICMP for IPv6 */ +#define HEADER_TYPE_IPv6_NONXT 59 /* IPv6-NoNxt No Next Header for IPv6 */ +#define HEADER_TYPE_IPv6_OPTS 60 /* IPv6-Opts IPv6 Destination Options */ +#define HEADER_TYPE_EIGRP 88 /* EIGRP */ +#define HEADER_TYPE_ETHERNET 97 /* Ethernet */ +#define HEADER_TYPE_L2TP 115 /* L2TP Layer Two Tunneling Protocol */ +#define HEADER_TYPE_SCTP 132 /* SCTP Stream Control Transmission P. */ +#define HEADER_TYPE_IPv6_MOBILE 135 /* Mobility Header */ +#define HEADER_TYPE_MPLS_IN_IP 137 /* MPLS-in-IP */ +#define HEADER_TYPE_ARP 2054 /* ARP Address Resolution Protocol */ +#define HEADER_TYPE_ICMPv6_OPTION 9997 /* ICMPv6 option */ +#define HEADER_TYPE_NEP 9998 /* Nping Echo Protocol */ +#define HEADER_TYPE_RAW_DATA 9999 /* Raw unknown data */ + +#define PRINT_DETAIL_LOW 1 +#define PRINT_DETAIL_MED 2 +#define PRINT_DETAIL_HIGH 3 + +#define DEFAULT_PRINT_DETAIL (PRINT_DETAIL_LOW) +#define DEFAULT_PRINT_DESCRIPTOR stdout + +class PacketElement { + + protected: + + int length; + PacketElement *next; /**< Next PacketElement (next proto header) */ + PacketElement *prev; /**< Prev PacketElement (previous proto header) */ + + public: + + PacketElement(); + + virtual ~PacketElement(){ + + } /* End of PacketElement destructor */ + + /** This function MUST be overwritten on ANY class that inherits from + * this one. Otherwise getBinaryBuffer will fail */ + virtual u8 * getBufferPointer(){ + netutil_fatal("getBufferPointer(): Attempting to use superclass PacketElement method.\n"); + return NULL; + } /* End of getBufferPointer() */ + + + /** Returns a buffer that contains the header of the packet + all the + * lower level headers and payload. Returned buffer should be ok to be + * passes to a send() call to be transferred trough a socket. + * @return a pointer to a free()able buffer that contains packet's binary + * data. + * @warning If there are linked elements, their getBinaryBuffer() method + * will be called recursively and the buffers that they return WILL be + * free()d as soon as we copy the data in our own allocated buffer. + * @warning Calls to this method may not ve very efficient since they + * always involved a few malloc()s and free()s. If you want efficiency + * use dumpToBinaryBuffer(); */ + virtual u8 * getBinaryBuffer(){ + u8 *ourbuff=NULL; + u8 *othersbuff=NULL; + u8 *totalbuff=NULL; + long otherslen=0; + + /* Get our own buffer address */ + if ( (ourbuff=getBufferPointer()) == NULL ){ + netutil_fatal("getBinaryBuffer(): Couldn't get own data pointer\n"); + } + if( next != NULL ){ /* There is some other packet element */ + othersbuff = next->getBinaryBuffer(); + otherslen=next->getLen(); + totalbuff=(u8 *)safe_zalloc(otherslen + length); + memcpy(totalbuff, ourbuff, length); + memcpy(totalbuff+length, othersbuff, otherslen); + free(othersbuff); + }else{ + totalbuff=(u8 *)safe_zalloc(length); + memcpy(totalbuff, ourbuff, length); + } + return totalbuff; + } /* End of getBinaryBuffer() */ + + + virtual int dumpToBinaryBuffer(u8* dst, int maxlen){ + u8 *ourbuff=NULL; + long ourlength=0; + /* Get our own buffer address and length */ + if ( (ourbuff=getBufferPointer()) == NULL || (ourlength=this->length) < 0 ) + netutil_fatal("getBinaryBuffer(): Couldn't get own data pointer\n"); + /* Copy our part of the buffer */ + if ( maxlen < ourlength ) + netutil_fatal("getBinaryBuffer(): Packet exceeds maximum length %d\n", maxlen); + memcpy( dst, ourbuff, ourlength); + /* If there are more elements, tell them to copy their part */ + if( next!= NULL ){ + next->dumpToBinaryBuffer(dst+ourlength, maxlen-ourlength); + } + return this->getLen(); + } /* End of dumpToBinaryBuffer() */ + + + /** Does the same as the previous one but it stores the length of the + * return buffer on the memory pointed by the supplied int pointer. */ + virtual u8 * getBinaryBuffer(int *len){ + u8 *buff = getBinaryBuffer(); + if( len != NULL ) + *len = getLen(); + return buff; + } /* End of getBinaryBuffer() */ + + + /** Returns the lenght of this PacketElement + the length of all the + * PacketElements that are next to it (are linked trough the "next" + * attribute). So for example, if we have IPv4Header p1, linked to + * a TCPHeader p2, representing a simple TCP SYN with no options, + * a call to p1.getLen() will return 20 (IP header with no options) + 20 + * (TCP header with no options) = 40 bytes. */ + int getLen() const { + /* If we have some other packet element linked, get its length */ + if (next!=NULL) + return length + next->getLen(); + else + return length; + } /* End of getLen() */ + + + /** Returns the address of the next PacketElement that is linked to this */ + virtual PacketElement *getNextElement() const { + return next; + } /* End of getNextElement() */ + + + /** Links current object with the next header in the protocol chain. Note + * that this method also links the next element with this one, calling + * setPrevElement(). */ + virtual int setNextElement(PacketElement *n){ + next=n; + if(next!=NULL) + next->setPrevElement(this); + return OP_SUCCESS; + } /* End of setNextElement() */ + + /** Sets attribute prev with the supplied pointer value. + * @warning Supplied pointer must point to a PacketElement object or + * an object that inherits from it. */ + virtual int setPrevElement(PacketElement *n){ + this->prev=n; + return OP_SUCCESS; + } /* End of setPrevElement() */ + + + /** Returns the address of the previous PacketElement that is linked to + * this one. + * @warning In many cases this function will return NULL since there is + * a high probability that the user of this class does not link + * PacketElements in both directions. Normally one would set attribute + * "next" of an IPHeader object to the TCPHeader that follows it, but + * not the other way around. */ + virtual PacketElement *getPrevElement(){ + return prev; + } /* End of getPrevElement() */ + + /** This method should be overwritten by any class that inherits from + * PacketElement. It should print the object contents and then call + * this->next->print(), providing this->next!=NULL */ + virtual int print(FILE *output, int detail) const { + if(this->next!=NULL) + this->next->print(output, detail); + return OP_SUCCESS; + } /* End of printf() */ + + virtual int print() const { + return print(DEFAULT_PRINT_DESCRIPTOR, DEFAULT_PRINT_DETAIL); + } + + virtual int print(int detail) const { + return print(DEFAULT_PRINT_DESCRIPTOR, detail); + } + + virtual void print_separator(FILE *output, int detail) const { + fprintf(output, " "); + } + + /* Returns the type of protocol an object represents. This method MUST + * be overwritten by all children. */ + virtual int protocol_id() const = 0; +}; + +#endif diff --git a/libnetutil/PacketParser.cc b/libnetutil/PacketParser.cc new file mode 100644 index 0000000000..49805ca168 --- /dev/null +++ b/libnetutil/PacketParser.cc @@ -0,0 +1,1708 @@ + +/*************************************************************************** + * PacketParser.cc -- The PacketParser Class offers methods to parse * + * received network packets. Its main purpose is to facilitate the * + * conversion of raw sequences of bytes into chains of objects of the * + * PacketElement family. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2010 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ + /* This code was originally part of the Nping tool. */ + +#include "PacketParser.h" +#include + +#define PKTPARSERDEBUG false + +PacketParser::PacketParser() { + this->reset(); +} /* End of PacketParser constructor */ + + +PacketParser::~PacketParser() { + +} /* End of PacketParser destructor */ + + +/** Sets every attribute to its default value- */ +void PacketParser::reset() { + +} /* End of PacketParser destructor */ + + +const char *PacketParser::header_type2string(int val){ + header_type_string_t header_types[]={ + {HEADER_TYPE_IPv6_HOPOPT, "IPv6 Hop-by-Hop"}, + {HEADER_TYPE_ICMPv4,"ICMPv4"}, + {HEADER_TYPE_IGMP,"IGMP"}, + {HEADER_TYPE_IPv4,"IPv4"}, + {HEADER_TYPE_TCP,"TCP"}, + {HEADER_TYPE_EGP,"EGP"}, + {HEADER_TYPE_UDP,"UDP"}, + {HEADER_TYPE_IPv6,"IPv6"}, + {HEADER_TYPE_IPv6_ROUTE,"IPv6-Route"}, + {HEADER_TYPE_IPv6_FRAG,"IPv6-Frag"}, + {HEADER_TYPE_GRE,"GRE"}, + {HEADER_TYPE_ESP,"ESP"}, + {HEADER_TYPE_AH,"AH"}, + {HEADER_TYPE_ICMPv6,"ICMPv6"}, + {HEADER_TYPE_IPv6_NONXT,"IPv6-NoNxt"}, + {HEADER_TYPE_IPv6_OPTS,"IPv6-Opts"}, + {HEADER_TYPE_EIGRP,"EIGRP"}, + {HEADER_TYPE_ETHERNET,"Ethernet"}, + {HEADER_TYPE_L2TP,"L2TP"}, + {HEADER_TYPE_SCTP,"SCTP"}, + {HEADER_TYPE_IPv6_MOBILE,"Mobility Header"}, + {HEADER_TYPE_MPLS_IN_IP,"MPLS-in-IP"}, + {HEADER_TYPE_ARP,"ARP"}, + {HEADER_TYPE_RAW_DATA,"Raw Data"}, + {0,NULL} + }; + int i=0; + for(i=0; header_types[i].str!=NULL; i++ ){ + if((int)header_types[i].type==val) + return header_types[i].str; + } + return NULL; +} /* End of header_type2string() */ + + + +#define MAX_HEADERS_IN_PACKET 32 +pkt_type_t *PacketParser::parse_packet(const u8 *pkt, size_t pktlen, bool eth_included){ + if(PKTPARSERDEBUG)printf("%s(%p, %lu)\n", __func__, pkt, (long unsigned)pktlen); + static pkt_type_t this_packet[MAX_HEADERS_IN_PACKET+1]; /* Packet structure array */ + u8 current_header=0; /* Current array position of "this_packet" */ + const u8 *curr_pkt=pkt; /* Pointer to current part of the packet */ + size_t curr_pktlen=pktlen; /* Remaining packet length */ + int ethlen=0, arplen=0; /* Aux length variables: link layer */ + int iplen=0,ip6len=0; /* Aux length variables: network layer */ + int tcplen=0,udplen=0,icmplen=0; /* Aux length variables: transport layer */ + int exthdrlen=0; /* Aux length variables: extension headers */ + int next_layer=0; /* Next header type to process */ + int expected=0; /* Next protocol expected */ + bool finished=false; /* Loop breaking flag */ + bool unknown_hdr=false; /* Indicates unknown header found */ + IPv4Header ip4; + IPv6Header ip6; + TCPHeader tcp; + UDPHeader udp; + ICMPv4Header icmp4; + ICMPv6Header icmp6; + EthernetHeader eth; + DestOptsHeader ext_dopts; + FragmentHeader ext_frag; + HopByHopHeader ext_hopt; + RoutingHeader ext_routing; + ARPHeader arp; + memset(this_packet, 0, sizeof(this_packet)); + + /* Decide which layer we have to start from */ + if( eth_included ){ + next_layer=LINK_LAYER; + expected=HEADER_TYPE_ETHERNET; + }else{ + next_layer=NETWORK_LAYER; + } + + /* Header processing loop */ + while(!finished && curr_pktlen>0 && current_header0){ + next_layer=APPLICATION_LAYER; + expected=HEADER_TYPE_RAW_DATA; + }else{ + finished=true; + } + }else{ + assert(finished==true); + } + /* IPv4 and IPv6 headers **************************************************/ + }else if(next_layer==NETWORK_LAYER){ + if(PKTPARSERDEBUG)puts("Next Layer=Network"); + /* Determine IP version */ + if (ip4.storeRecvData(curr_pkt, curr_pktlen)==OP_FAILURE){ + unknown_hdr=true; + break; + } + + /* IP version 4 ---------------------------------*/ + if(ip4.getVersion()==4){ + if( (iplen=ip4.validate())==OP_FAILURE){ + unknown_hdr=true; + break; + } + /* Determine next header type */ + switch(ip4.getNextProto()){ + case HEADER_TYPE_ICMPv4: + next_layer=TRANSPORT_LAYER; + expected=HEADER_TYPE_ICMPv4; + break; + case HEADER_TYPE_IPv4: /* IP in IP */ + next_layer=NETWORK_LAYER; + expected=HEADER_TYPE_IPv4; + break; + case HEADER_TYPE_TCP: + next_layer=TRANSPORT_LAYER; + expected=HEADER_TYPE_TCP; + break; + case HEADER_TYPE_UDP: + next_layer=TRANSPORT_LAYER; + expected=HEADER_TYPE_UDP; + break; + case HEADER_TYPE_IPv6: /* IPv6 in IPv4 */ + next_layer=NETWORK_LAYER; + expected=HEADER_TYPE_IPv6; + break; + default: + next_layer=APPLICATION_LAYER; + expected=HEADER_TYPE_RAW_DATA; + break; + } + this_packet[current_header].length=iplen; + this_packet[current_header++].type=HEADER_TYPE_IPv4; + ip4.reset(); + curr_pkt+=iplen; + curr_pktlen-=iplen; + /* IP version 6 ---------------------------------*/ + }else if(ip4.getVersion()==6){ + ip4.reset(); + if (ip6.storeRecvData(curr_pkt, curr_pktlen)==OP_FAILURE){ + unknown_hdr=true; + break; + } + if( (ip6len=ip6.validate())==OP_FAILURE ){ + unknown_hdr=true; + break; + } + switch( ip6.getNextHeader() ){ + case HEADER_TYPE_ICMPv6: + next_layer=TRANSPORT_LAYER; + expected=HEADER_TYPE_ICMPv6; + break; + case HEADER_TYPE_IPv4: /* IPv4 in IPv6 */ + next_layer=NETWORK_LAYER; + expected=HEADER_TYPE_IPv4; + break; + case HEADER_TYPE_TCP: + next_layer=TRANSPORT_LAYER; + expected=HEADER_TYPE_TCP; + break; + case HEADER_TYPE_UDP: + next_layer=TRANSPORT_LAYER; + expected=HEADER_TYPE_UDP; + break; + case HEADER_TYPE_IPv6: /* IPv6 in IPv6 */ + next_layer=NETWORK_LAYER; + expected=HEADER_TYPE_IPv6; + break; + case HEADER_TYPE_IPv6_HOPOPT: + next_layer=EXTHEADERS_LAYER; + expected=HEADER_TYPE_IPv6_HOPOPT; + break; + case HEADER_TYPE_IPv6_OPTS: + next_layer=EXTHEADERS_LAYER; + expected=HEADER_TYPE_IPv6_OPTS; + break; + case HEADER_TYPE_IPv6_ROUTE: + next_layer=EXTHEADERS_LAYER; + expected=HEADER_TYPE_IPv6_ROUTE; + break; + case HEADER_TYPE_IPv6_FRAG: + next_layer=EXTHEADERS_LAYER; + expected=HEADER_TYPE_IPv6_FRAG; + break; + default: + next_layer=APPLICATION_LAYER; + expected=HEADER_TYPE_RAW_DATA; + break; + } + this_packet[current_header].length=ip6len; + this_packet[current_header++].type=HEADER_TYPE_IPv6; + ip6.reset(); + curr_pkt+=ip6len; + curr_pktlen-=ip6len; + /* Bogus IP version -----------------------------*/ + }else{ + /* Wrong IP version, treat as raw data. */ + next_layer=APPLICATION_LAYER; + expected=HEADER_TYPE_RAW_DATA; + } + /* TCP, UDP, ICMPv4 and ICMPv6 headers ************************************/ + }else if(next_layer==TRANSPORT_LAYER){ + if(PKTPARSERDEBUG)puts("Next Layer=Transport"); + if(expected==HEADER_TYPE_TCP){ + if(PKTPARSERDEBUG)puts("Expected Layer=TCP"); + if(tcp.storeRecvData(curr_pkt, curr_pktlen)==OP_FAILURE ){ + unknown_hdr=true; + break; + } + if( (tcplen=tcp.validate())==OP_FAILURE){ + unknown_hdr=true; + break; + } + expected=HEADER_TYPE_RAW_DATA; + this_packet[current_header].length=tcplen; + this_packet[current_header++].type=HEADER_TYPE_TCP; + tcp.reset(); + curr_pkt+=tcplen; + curr_pktlen-=tcplen; + next_layer=APPLICATION_LAYER; + }else if(expected==HEADER_TYPE_UDP){ + if(PKTPARSERDEBUG)puts("Expected Layer=UDP"); + if(udp.storeRecvData(curr_pkt, curr_pktlen)==OP_FAILURE ){ + unknown_hdr=true; + break; + } + if( (udplen=udp.validate())==OP_FAILURE){ + unknown_hdr=true; + break; + } + expected=HEADER_TYPE_RAW_DATA; + this_packet[current_header].length=udplen; + this_packet[current_header++].type=HEADER_TYPE_UDP; + udp.reset(); + curr_pkt+=udplen; + curr_pktlen-=udplen; + next_layer=APPLICATION_LAYER; + }else if(expected==HEADER_TYPE_ICMPv4){ + if(PKTPARSERDEBUG)puts("Expected Layer=ICMPv4"); + if(icmp4.storeRecvData(curr_pkt, curr_pktlen)==OP_FAILURE ){ + unknown_hdr=true; + break; + } + if( (icmplen=icmp4.validate())==OP_FAILURE){ + unknown_hdr=true; + break; + } + switch( icmp4.getType() ){ + /* Types that include an IPv4 packet as payload */ + case ICMP_UNREACH: + case ICMP_TIMXCEED: + case ICMP_PARAMPROB: + case ICMP_SOURCEQUENCH: + case ICMP_REDIRECT: + next_layer=NETWORK_LAYER; + expected=HEADER_TYPE_IPv4; + break; + /* ICMP types that include misc payloads (or no payload) */ + default: + expected=HEADER_TYPE_RAW_DATA; + next_layer=APPLICATION_LAYER; + break; + } + this_packet[current_header].length=icmplen; + this_packet[current_header++].type=HEADER_TYPE_ICMPv4; + icmp4.reset(); + curr_pkt+=icmplen; + curr_pktlen-=icmplen; + }else if(expected==HEADER_TYPE_ICMPv6){ + if(PKTPARSERDEBUG)puts("Expected Layer=ICMPv6"); + if(icmp6.storeRecvData(curr_pkt, curr_pktlen)==OP_FAILURE){ + unknown_hdr=true; + break; + } + if( (icmplen=icmp6.validate())==OP_FAILURE){ + unknown_hdr=true; + break; + } + switch( icmp6.getType() ){ + /* Types that include an IPv6 packet as payload */ + case ICMPv6_UNREACH: + case ICMPv6_PKTTOOBIG: + case ICMPv6_TIMXCEED: + case ICMPv6_PARAMPROB: + next_layer=NETWORK_LAYER; + expected=HEADER_TYPE_IPv6; + break; + /* ICMPv6 types that include misc payloads (or no payload) */ + default: + expected=HEADER_TYPE_RAW_DATA; + next_layer=APPLICATION_LAYER; + break; + } + this_packet[current_header].length=icmplen; + this_packet[current_header++].type=HEADER_TYPE_ICMPv6; + icmp6.reset(); + curr_pkt+=icmplen; + curr_pktlen-=icmplen; + }else{ + /* Wrong application layer protocol, treat as raw data. */ + next_layer=APPLICATION_LAYER; + expected=HEADER_TYPE_RAW_DATA; + } + + /* IPv6 Extension Headers */ + }else if(next_layer==EXTHEADERS_LAYER){ + if(PKTPARSERDEBUG)puts("Next Layer=ExtHdr"); + u8 ext_next=0; + /* Hop-by-Hop Options */ + if(expected==HEADER_TYPE_IPv6_HOPOPT){ + if(PKTPARSERDEBUG)puts("Expected=Hopt"); + if(ext_hopt.storeRecvData(curr_pkt, curr_pktlen)==OP_FAILURE ){ + unknown_hdr=true; + break; + } + if( (exthdrlen=ext_hopt.validate())==OP_FAILURE){ + unknown_hdr=true; + break; + } + ext_next=ext_hopt.getNextHeader(); + ext_hopt.reset(); + /* Routing Header */ + }else if(expected==HEADER_TYPE_IPv6_ROUTE){ + if(PKTPARSERDEBUG)puts("Expected=Route"); + if(ext_routing.storeRecvData(curr_pkt, curr_pktlen)==OP_FAILURE ){ + unknown_hdr=true; + break; + } + if( (exthdrlen=ext_routing.validate())==OP_FAILURE){ + unknown_hdr=true; + break; + } + ext_next=ext_routing.getNextHeader(); + ext_routing.reset(); + /* Fragmentation Header */ + }else if(expected==HEADER_TYPE_IPv6_FRAG){ + if(PKTPARSERDEBUG)puts("Expected=Frag"); + if(ext_frag.storeRecvData(curr_pkt, curr_pktlen)==OP_FAILURE ){ + unknown_hdr=true; + break; + } + if( (exthdrlen=ext_frag.validate())==OP_FAILURE){ + unknown_hdr=true; + break; + } + ext_next=ext_frag.getNextHeader(); + ext_frag.reset(); + /* Destination Options Header */ + }else if(expected==HEADER_TYPE_IPv6_OPTS){ + if(PKTPARSERDEBUG)puts("Expected=Dopts"); + if(ext_dopts.storeRecvData(curr_pkt, curr_pktlen)==OP_FAILURE ){ + unknown_hdr=true; + break; + } + if( (exthdrlen=ext_dopts.validate())==OP_FAILURE){ + unknown_hdr=true; + break; + } + ext_next=ext_dopts.getNextHeader(); + ext_dopts.reset(); + }else{ + /* Should never happen. */ + unknown_hdr=true; + break; + } + + /* Update the info for this header */ + this_packet[current_header].length=exthdrlen; + this_packet[current_header++].type=expected; + curr_pkt+=exthdrlen; + curr_pktlen-=exthdrlen; + + /* Lets's see what comes next */ + switch(ext_next){ + case HEADER_TYPE_ICMPv6: + next_layer=TRANSPORT_LAYER; + expected=HEADER_TYPE_ICMPv6; + break; + case HEADER_TYPE_IPv4: /* IPv4 in IPv6 */ + next_layer=NETWORK_LAYER; + expected=HEADER_TYPE_IPv4; + break; + case HEADER_TYPE_TCP: + next_layer=TRANSPORT_LAYER; + expected=HEADER_TYPE_TCP; + break; + case HEADER_TYPE_UDP: + next_layer=TRANSPORT_LAYER; + expected=HEADER_TYPE_UDP; + break; + case HEADER_TYPE_IPv6: /* IPv6 in IPv6 */ + next_layer=NETWORK_LAYER; + expected=HEADER_TYPE_IPv6; + break; + case HEADER_TYPE_IPv6_HOPOPT: + next_layer=EXTHEADERS_LAYER; + expected=HEADER_TYPE_IPv6_HOPOPT; + break; + case HEADER_TYPE_IPv6_OPTS: + next_layer=EXTHEADERS_LAYER; + expected=HEADER_TYPE_IPv6_OPTS; + break; + case HEADER_TYPE_IPv6_ROUTE: + next_layer=EXTHEADERS_LAYER; + expected=HEADER_TYPE_IPv6_ROUTE; + break; + case HEADER_TYPE_IPv6_FRAG: + next_layer=EXTHEADERS_LAYER; + expected=HEADER_TYPE_IPv6_FRAG; + break; + default: + next_layer=APPLICATION_LAYER; + expected=HEADER_TYPE_RAW_DATA; + break; + } + + /* Miscellaneous payloads *************************************************/ + }else{ // next_layer==APPLICATION_LAYER + if(PKTPARSERDEBUG)puts("Next Layer=Application"); + if(curr_pktlen>0){ + //if(expected==HEADER_TYPE_DNS){ + //}else if(expected==HEADER_TYPE_HTTP){ + //}... ETC + this_packet[current_header].length=curr_pktlen; + this_packet[current_header++].type=HEADER_TYPE_RAW_DATA; + curr_pktlen=0; + } + finished=true; + } + } /* End of header processing loop */ + + /* If we couldn't validate some header, treat that header and any remaining + * data, as raw application data. */ + if (unknown_hdr==true){ + if(curr_pktlen>0){ + if(PKTPARSERDEBUG)puts("Unknown layer found. Treating it as raw data."); + this_packet[current_header].length=curr_pktlen; + this_packet[current_header++].type=HEADER_TYPE_RAW_DATA; + } + } + + return this_packet; +} /* End of parse_received_packet() */ + + +/* TODO: remove */ +int PacketParser::dummy_print_packet_type(const u8 *pkt, size_t pktlen, bool eth_included){ + pkt_type_t *packetheaders=PacketParser::parse_packet(pkt, pktlen, eth_included); + for(int i=0; packetheaders[i].length!=0; i++){ + printf("%s:", header_type2string(packetheaders[i].type)); + } + printf("\n"); + return OP_SUCCESS; +} /* End of dummy_print_packet_type() */ + + +int PacketParser::dummy_print_packet(const u8 *pkt, size_t pktlen, bool eth_included){ + PacketElement *me=NULL, *aux=NULL; + if( (me=split(pkt, pktlen, eth_included))==NULL ) + return OP_FAILURE; + else{ + me->print(stdout, PRINT_DETAIL_HIGH); + printf("\n"); + } + /* Free the structs */ + while(me!=NULL){ + aux=me->getNextElement(); + delete me; + me=aux; + } + return OP_SUCCESS; +} /* End of dummy_print_packet() */ + + + +/** For a given packet, this method determines where the application layer data + * begins. It returs a positive offset if any application data was found, zero + * if the packet did not contain application data and a negative integer in + * case of error. */ +int PacketParser::payload_offset(const u8 *pkt, size_t pktlen, bool link_included){ + PacketElement *me=NULL, *aux=NULL; + size_t offset=pktlen; /* Initially, point to the end of the packet. */ + + /* Safe checks*/ + if(pkt==NULL || pktlen<=0) + return -1; + + dummy_print_packet_type(pkt, pktlen, link_included); + + /* Split the packet into separate protocol headers */ + if( (me=split(pkt, pktlen, link_included))==NULL ) + return -2; + else{ + aux=me; + } + + /* Find if there is application data and where it begins */ + while(me!=NULL){ + /* When we find application data, we compute the offset by substacting the + length of the application data from the packet's total length */ + if(me->protocol_id()==HEADER_TYPE_RAW_DATA){ + offset=pktlen-me->getLen(); + break; + me=me->getNextElement(); + }else{ + me=me->getNextElement(); + } + } + + /* Free the structs */ + me=aux; + while(me!=NULL){ + aux=me->getNextElement(); + delete me; + me=aux; + } + + /* Return 0 if we didn't find any application data */ + if(offset==pktlen){ + return 0; + }else{ + return offset; + } +} /* End of payload_offset() */ + + + + +PacketElement *PacketParser::split(const u8 *pkt, size_t pktlen){ + return split(pkt, pktlen, false); +} /* End of split() */ + + +PacketElement *PacketParser::split(const u8 *pkt, size_t pktlen, bool eth_included){ + pkt_type_t *packetheaders=NULL; + const u8 *curr_pkt=pkt; + PacketElement *first=NULL; + PacketElement *last=NULL; + IPv4Header *ip4=NULL; + IPv6Header *ip6=NULL; + DestOptsHeader *ext_dopts=NULL; + FragmentHeader *ext_frag=NULL; + HopByHopHeader *ext_hopt=NULL; + RoutingHeader *ext_routing=NULL; + TCPHeader *tcp=NULL; + UDPHeader *udp=NULL; + ICMPv4Header *icmp4=NULL; + ICMPv6Header *icmp6=NULL; + EthernetHeader *eth=NULL; + ARPHeader *arp=NULL; + RawData *raw=NULL; + + /* Analyze the packet. This returns a list of header types and lengths */ + if((packetheaders=PacketParser::parse_packet(pkt, pktlen, eth_included))==NULL) + return NULL; + + /* Store each header in its own PacketHeader object type */ + for(int i=0; packetheaders[i].length!=0; i++){ + + switch(packetheaders[i].type){ + + case HEADER_TYPE_ETHERNET: + eth=new EthernetHeader(); + eth->storeRecvData(curr_pkt, packetheaders[i].length); + if(first==NULL){ + first=eth; + }else{ + last->setNextElement(eth); + } + last=eth; + break; + + case HEADER_TYPE_ARP: + arp=new ARPHeader(); + arp->storeRecvData(curr_pkt, packetheaders[i].length); + if(first==NULL){ + first=arp; + }else{ + last->setNextElement(arp); + } + last=arp; + break; + + case HEADER_TYPE_IPv4: + ip4=new IPv4Header(); + ip4->storeRecvData(curr_pkt, packetheaders[i].length); + if(first==NULL){ + first=ip4; + }else{ + last->setNextElement(ip4); + } + last=ip4; + break; + + case HEADER_TYPE_IPv6: + ip6=new IPv6Header(); + ip6->storeRecvData(curr_pkt, packetheaders[i].length); + if(first==NULL){ + first=ip6; + }else{ + last->setNextElement(ip6); + } + last=ip6; + break; + + case HEADER_TYPE_TCP: + tcp=new TCPHeader(); + tcp->storeRecvData(curr_pkt, packetheaders[i].length); + if(first==NULL){ + first=tcp; + }else{ + last->setNextElement(tcp); + } + last=tcp; + break; + + case HEADER_TYPE_UDP: + udp=new UDPHeader(); + udp->storeRecvData(curr_pkt, packetheaders[i].length); + if(first==NULL){ + first=udp; + }else{ + last->setNextElement(udp); + } + last=udp; + break; + + case HEADER_TYPE_ICMPv4: + icmp4=new ICMPv4Header(); + icmp4->storeRecvData(curr_pkt, packetheaders[i].length); + if(first==NULL){ + first=icmp4; + }else{ + last->setNextElement(icmp4); + } + last=icmp4; + break; + + case HEADER_TYPE_ICMPv6: + icmp6=new ICMPv6Header(); + icmp6->storeRecvData(curr_pkt, packetheaders[i].length); + if(first==NULL){ + first=icmp6; + }else{ + last->setNextElement(icmp6); + } + last=icmp6; + break; + + case HEADER_TYPE_IPv6_HOPOPT: + ext_hopt=new HopByHopHeader(); + ext_hopt->storeRecvData(curr_pkt, packetheaders[i].length); + if(first==NULL){ + first=ext_hopt; + }else{ + last->setNextElement(ext_hopt); + } + last=ext_hopt; + break; + + case HEADER_TYPE_IPv6_ROUTE: + ext_routing=new RoutingHeader(); + ext_routing->storeRecvData(curr_pkt, packetheaders[i].length); + if(first==NULL){ + first=ext_routing; + }else{ + last->setNextElement(ext_routing); + } + last=ext_routing; + break; + + case HEADER_TYPE_IPv6_FRAG: + ext_frag=new FragmentHeader(); + ext_frag->storeRecvData(curr_pkt, packetheaders[i].length); + if(first==NULL){ + first=ext_frag; + }else{ + last->setNextElement(ext_frag); + } + last=ext_frag; + break; + + case HEADER_TYPE_IPv6_OPTS: + ext_dopts=new DestOptsHeader(); + ext_dopts->storeRecvData(curr_pkt, packetheaders[i].length); + if(first==NULL){ + first=ext_dopts; + }else{ + last->setNextElement(ext_dopts); + } + last=ext_dopts; + break; + + case HEADER_TYPE_RAW_DATA: + default: + raw=new RawData(); + raw->storeRecvData(curr_pkt, packetheaders[i].length); + if(first==NULL){ + first=raw; + }else{ + last->setNextElement(raw); + } + last=raw; + break; + } + curr_pkt+=packetheaders[i].length; + } + return first; +} /* End of split() */ + + +/* This method frees a chain of PacketElement objects. Note that objects in + * the chain are freed by calling "delete" on them, so only those instances + * that have been obtained through a call to "new" should be passed to this + * method. Chains returned by PacketParser::split() are safe to use with this.*/ +int PacketParser::freePacketChain(PacketElement *first){ + PacketElement *curr=first; + PacketElement *next=NULL; + while(curr!=NULL){ + next=curr->getNextElement(); + delete curr; + curr=next; + } + return OP_SUCCESS; +} /* End of freePacketChain() */ + + +/* This method is for debugging purposes only. It tests the packet parser and + * the PacketElement class family. Basically it checks that the supplied + * chain of PacketElements can be serialized and de-serialized correctly. + * Returns NULL on success or an error string in case of failure. */ +const char *PacketParser::test_packet_parser(PacketElement *test_pkt){ + const char *errmsg=NULL; + PacketElement *parsed_pkt=NULL; + PacketElement *orig_pkt=NULL; + PacketElement *new_pkt=NULL; + u8 *mypktbuff2=NULL; + u8 *mypktbuff=NULL; + + if(test_pkt==NULL){ + errmsg="NULL pointer supplied"; + goto end; + } + + /* Generate a serialized version of the packet */ + mypktbuff=(u8 *)safe_malloc(test_pkt->getLen()); + test_pkt->dumpToBinaryBuffer(mypktbuff, test_pkt->getLen()); + + /* Generate a chain of PacketElement objects from the serialized version. */ + parsed_pkt=PacketParser::split(mypktbuff, test_pkt->getLen()); + + if(parsed_pkt==NULL){ + errmsg="PacketParser::split() returned NULL"; + goto end; + } + if(parsed_pkt->getLen()!=test_pkt->getLen()){ + errmsg="Packets have different lengths"; + goto end; + } + + /* Generate a serialized version of the new chain */ + mypktbuff2=(u8 *)safe_malloc(parsed_pkt->getLen()); + parsed_pkt->dumpToBinaryBuffer(mypktbuff2, parsed_pkt->getLen()); + + /* Make sure both packets produce the exact same binary buffer */ + if(memcmp(mypktbuff, mypktbuff2, parsed_pkt->getLen())!=0){ + errmsg="The two packets do not result in the same binary buffer"; + goto end; + } + + /* Now let's check that both chains have the same number and type of + * PacketElements. */ + orig_pkt=test_pkt; + new_pkt=parsed_pkt; + while(orig_pkt!=NULL && new_pkt!=NULL){ + if(orig_pkt->protocol_id() != new_pkt->protocol_id() ){ + errmsg="Protocol IDs do not match"; + goto end; + } + orig_pkt=orig_pkt->getNextElement(); + new_pkt=new_pkt->getNextElement(); + } + + if(orig_pkt!=NULL || new_pkt!=NULL){ + errmsg="The two packets do not have the same number of chained elements."; + goto end; + } + + end: + /* Free our allocations */ + if(mypktbuff!=NULL) + free(mypktbuff); + if(mypktbuff2!=NULL) + free(mypktbuff2); + if(parsed_pkt!=NULL) + PacketParser::freePacketChain(parsed_pkt); + + /* If everything went well, errmsg should still be NULL. Otherwise it + * should point to an error message.*/ + return errmsg; +} + + + +/* Returns true if the supplied "rcvd" packet is a response to the "sent" packet. + * This method currently handles IPv4, IPv6, ICMPv4, ICMPv6, TCP and UDP. Here + * some examples of what can be matched using it: + * + * Probe: TCP SYN -> Response TCP SYN|ACK + * Probe: TCP SYN -> Response TCP RST|ACK + * Probe: UDP:53 -> Response UDP from port 53. + * Probe ICMP Echo -> Response ICMP Echo reply + * Probe ICMPv6 Neighbor Solicitation -> Response ICMPv6 Neighbor Advert + * Probe Malformed IPv6 -> Response ICMPv6 Parameter Problem + * Probe MLDv1 Query -> Response MLDv1 Report + * Probe ICMP Timestamp request -> Response ICMP timestamp response + * etc... + * + * Note that ICMP error messages are matched against sent probes (e.g: an ICMP + * Parameter Problem generated as a result of an invalid TCP segment is matched + * positively with the original TCP segment). Therefore, the caller must ensure + * that the received packet is what it expects before using it (e.g: the packet + * is an actual TCP packet, not an ICMP error). + * + * Warning: this method assumes that the probes you send are reasonably + * different from each other. Don't expect a 100% accuracy if you send a bunch + * of TCP segments with the same source and destination port numbers, or a + * bunch of ICMP messages with the same identifier and sequence number. */ +bool PacketParser::is_response(PacketElement *sent, PacketElement *rcvd){ + if(PKTPARSERDEBUG)printf("%s(): called\n", __func__); + + if(sent==NULL || rcvd==NULL) + return false; + + /* If any of the packets is encapsulated in an Ethernet frame, strip the + * link layer header before proceeding with the matching process. */ + if(rcvd->protocol_id()==HEADER_TYPE_ETHERNET) + if( (rcvd=rcvd->getNextElement())==NULL) + return false; + if(sent->protocol_id()==HEADER_TYPE_ETHERNET) + if( (sent=sent->getNextElement())==NULL) + return false; + + /* Make sure both packets have the same network layer and that it is IP */ + if(rcvd->protocol_id()!=sent->protocol_id()) + return false; + if(rcvd->protocol_id()!=HEADER_TYPE_IPv6 && rcvd->protocol_id()!=HEADER_TYPE_IPv4) + return false; + if(PKTPARSERDEBUG)printf("%s(): Both packets use IP.\n", __func__); + + /* Handle the network layer with a more specific class */ + NetworkLayerElement *rcvd_ip=(NetworkLayerElement *)rcvd; + NetworkLayerElement *sent_ip=(NetworkLayerElement *)sent; + + /* Ensure the packet comes from the host we sent the probe to */ + if( memcmp(rcvd_ip->getSourceAddress(), sent_ip->getDestinationAddress(), rcvd_ip->getAddressLength())!=0 ) + return false; + /* Ensure the received packet is destined to us */ + if( memcmp(rcvd_ip->getDestinationAddress(), sent_ip->getSourceAddress(), rcvd_ip->getAddressLength())!=0 ) + return false; + + if(PKTPARSERDEBUG)printf("%s(): Src and Dst addresses make sense.\n", __func__); + + /* Skip layers until we find ICMP or a transport protocol */ + PacketElement *rcvd_layer4=rcvd_ip->getNextElement(); + PacketElement *sent_layer4=sent_ip->getNextElement(); + while(rcvd_layer4!=NULL){ + if(rcvd_layer4->protocol_id()==HEADER_TYPE_UDP || rcvd_layer4->protocol_id()==HEADER_TYPE_TCP || + rcvd_layer4->protocol_id()==HEADER_TYPE_ICMPv4 || rcvd_layer4->protocol_id()==HEADER_TYPE_ICMPv6 ){ + break; + }else{ + rcvd_layer4=rcvd_layer4->getNextElement(); + } + } + while(sent_layer4!=NULL){ + if(sent_layer4->protocol_id()==HEADER_TYPE_UDP || sent_layer4->protocol_id()==HEADER_TYPE_TCP || + sent_layer4->protocol_id()==HEADER_TYPE_ICMPv4 || sent_layer4->protocol_id()==HEADER_TYPE_ICMPv6 ){ + break; + }else{ + sent_layer4=sent_layer4->getNextElement(); + } + } + if(rcvd_layer4==NULL || sent_layer4==NULL) + return false; + + if(PKTPARSERDEBUG)printf("%s(): Layer 4 found for both packets.\n", __func__); + + /* If we get here it means that both packets have a proper layer4 protocol + * header. Now we have to check which type are they and see if a probe-response + * relation can be established. */ + if(sent_layer4->protocol_id()==HEADER_TYPE_ICMPv6 || sent_layer4->protocol_id()==HEADER_TYPE_ICMPv4){ + + if(PKTPARSERDEBUG)printf("%s(): Sent packet is ICMP.\n", __func__); + + /* Make sure received packet is ICMP (we only expect ICMP responses for + * ICMP probes) */ + if(rcvd_layer4->protocol_id()!=HEADER_TYPE_ICMPv6 && rcvd_layer4->protocol_id()!=HEADER_TYPE_ICMPv4 ) + return false; + + /* Make sure both packets have the same ICMP version */ + if(sent_layer4->protocol_id()!=rcvd_layer4->protocol_id()) + return false; + + if(PKTPARSERDEBUG)printf("%s(): Received packet is ICMP too.\n", __func__); + + /* Check if the received ICMP is an error message. We don't care which kind + * of error message it is. The only important thing is that error messages + * contain a copy of the original datagram, and that's what we want to + * match against the sent probe. */ + if( ((ICMPHeader *)rcvd_layer4)->isError() ){ + NetworkLayerElement *iperror=(NetworkLayerElement *)rcvd_layer4->getNextElement(); + + if(PKTPARSERDEBUG)printf("%s(): Received ICMP is an error message.\n", __func__); + + /* ICMP error message must contain the original datagram */ + if(iperror==NULL) + return false; + + /* The first header must be IP */ + if(iperror->protocol_id()!=HEADER_TYPE_IPv6 && iperror->protocol_id()!=HEADER_TYPE_IPv4) + return false; + + /* The IP version must match the probe's */ + if(iperror->protocol_id()!=sent_ip->protocol_id()) + return false; + + /* Source and destination addresses must match the probe's */ + if( memcmp(iperror->getSourceAddress(), sent_ip->getSourceAddress(), iperror->getAddressLength())!=0 ) + return false; + if( memcmp(iperror->getDestinationAddress(), sent_ip->getDestinationAddress(), iperror->getAddressLength())!=0 ) + return false; + + /* So far we've verified that the ICMP error contains an IP datagram that matches + * what we sent. Now, let's find the upper layer ICMP header (skip extension + * headers until we find ICMP) */ + ICMPHeader *inner_icmp=(ICMPHeader *)iperror->getNextElement(); + while(inner_icmp!=NULL){ + if(inner_icmp->protocol_id()==HEADER_TYPE_ICMPv4 || inner_icmp->protocol_id()==HEADER_TYPE_ICMPv6 ){ + break; + }else{ + inner_icmp=(ICMPHeader *)inner_icmp->getNextElement(); + } + } + if(inner_icmp==NULL) + return false; + + /* If we get here it means that we've found an ICMP header inside the + * ICMP error message that we received. First of all, check that the + * ICMP version matches what we sent. */ + if(sent_layer4->protocol_id() != inner_icmp->protocol_id()) + return false; + + /* Make sure ICMP type and code match */ + if( ((ICMPHeader*)sent_layer4)->getType() != inner_icmp->getType() ) + return false; + if( ((ICMPHeader*)sent_layer4)->getCode() != inner_icmp->getCode() ) + return false; + + /* Now go into a bit of detail and try to determine if both headers + * are equal, comparing the values of specific fields. */ + if(sent_layer4->protocol_id()==HEADER_TYPE_ICMPv6){ + ICMPv6Header *sent_icmp6=(ICMPv6Header *)sent_layer4; + ICMPv6Header *inner_icmp6=(ICMPv6Header *)inner_icmp; + + switch(sent_icmp6->getType()){ + case ICMPv6_UNREACH: + case ICMPv6_TIMXCEED : + /* For these we cannot guarantee that the received ICMPv6 error + * packet included data beyond the inner ICMPv6 header, so we just + * assume that they are a match to the sent probe. (We shouldn't + * really be sending ICMPv6 error messages and expect ICMPv6 error + * responses that contain our ICMv6P error messages, should we? + * Well, even if we do, there is a good chance we are able to match + * those responses with the original probe) */ + break; + + case ICMPv6_PKTTOOBIG: + if(sent_icmp6->getMTU() != inner_icmp6->getMTU()) + return false; + break; + + case ICMPv6_PARAMPROB: + if(sent_icmp6->getPointer() != inner_icmp6->getPointer()) + return false; + break; + + case ICMPv6_ECHO: + case ICMPv6_ECHOREPLY: + if(sent_icmp6->getIdentifier() != inner_icmp6->getIdentifier()) + return false; + if(sent_icmp6->getSequence() != inner_icmp6->getSequence()) + return false; + break; + + case ICMPv6_ROUTERSOLICIT: + /* Here we do not have much to compare, so we just test that + * the reserved field contains the same value, usually zero. */ + if(sent_icmp6->getReserved()!=inner_icmp6->getReserved()) + return false; + break; + + case ICMPv6_ROUTERADVERT: + if(sent_icmp6->getCurrentHopLimit() != inner_icmp6->getCurrentHopLimit() ) + return false; + if(sent_icmp6->getRouterLifetime() != inner_icmp6->getRouterLifetime() ) + return false; + if(sent_icmp6->getReachableTime() != inner_icmp6->getReachableTime() ) + return false; + if(sent_icmp6->getRetransmissionTimer() != inner_icmp6->getRetransmissionTimer() ) + return false; + break; + + case ICMPv6_REDIRECT: + if( memcmp(sent_icmp6->getTargetAddress().s6_addr, inner_icmp6->getTargetAddress().s6_addr, 16) !=0 ) + return false; + if( memcmp(sent_icmp6->getDestinationAddress().s6_addr, inner_icmp6->getDestinationAddress().s6_addr, 16) !=0 ) + return false; + break; + + case ICMPv6_NGHBRSOLICIT: + case ICMPv6_NGHBRADVERT: + if( memcmp(sent_icmp6->getTargetAddress().s6_addr, inner_icmp6->getTargetAddress().s6_addr, 16) !=0 ) + return false; + break; + + case ICMPv6_RTRRENUM: + if(sent_icmp6->getSequence() != inner_icmp6->getSequence() ) + return false; + if(sent_icmp6->getSegmentNumber() != inner_icmp6->getSegmentNumber() ) + return false; + if(sent_icmp6->getMaxDelay() != inner_icmp6->getMaxDelay() ) + return false; + if(sent_icmp6->getFlags() != inner_icmp6->getFlags() ) + return false; + break; + + case ICMPv6_NODEINFOQUERY: + case ICMPv6_NODEINFORESP: + if(sent_icmp6->getNodeInfoFlags() != inner_icmp6->getNodeInfoFlags() ) + return false; + if( memcmp(sent_icmp6->getNonce(), inner_icmp6->getNonce(), NI_NONCE_LEN)!=0 ) + return false; + if(sent_icmp6->getQtype() != inner_icmp6->getQtype() ) + return false; + break; + + + case ICMPv6_GRPMEMBQUERY: + case ICMPv6_GRPMEMBREP: + case ICMPv6_GRPMEMBRED: + case ICMPv6_INVNGHBRSOLICIT: + case ICMPv6_INVNGHBRADVERT: + case ICMPv6_MLDV2: + case ICMPv6_AGENTDISCOVREQ: + case ICMPv6_AGENTDISCOVREPLY: + case ICMPv6_MOBPREFIXSOLICIT: + case ICMPv6_MOBPREFIXADVERT: + case ICMPv6_CERTPATHSOLICIT: + case ICMPv6_CERTPATHADVERT: + case ICMPv6_EXPMOBILITY: + case ICMPv6_MRDADVERT: + case ICMPv6_MRDSOLICIT: + case ICMPv6_MRDTERMINATE: + case ICMPv6_FMIPV6: + /* All these types are not currently implemented but since the + * sent_icmp.getType() has returned such type, we assume + * that there is a match (don't return false here). */ + break; + + default: + /* Do not match ICMPv6 types we don't know about */ + return false; + break; + } + }else if(sent_layer4->protocol_id()==HEADER_TYPE_ICMPv4){ + ICMPv4Header *sent_icmp4=(ICMPv4Header *)sent_layer4; + ICMPv4Header *inner_icmp4=(ICMPv4Header *)inner_icmp; + + switch(sent_icmp4->getType()){ + case ICMP_ECHOREPLY: + case ICMP_ECHO: + case ICMP_TSTAMP: + case ICMP_TSTAMPREPLY: + case ICMP_INFO: + case ICMP_INFOREPLY: + case ICMP_MASK: + case ICMP_MASKREPLY: + case ICMP_DOMAINNAME: + case ICMP_DOMAINNAMEREPLY: + /* Check the message identifier and sequence number */ + if(sent_icmp4->getIdentifier() != inner_icmp4->getIdentifier()) + return false; + if(sent_icmp4->getSequence() != inner_icmp4->getSequence()) + return false; + break; + + case ICMP_ROUTERADVERT: + /* Check only the main fields, no need to parse the whole list + * of addresses (maybe we didn't even get enough octets to + * check that). */ + if(sent_icmp4->getNumAddresses() != inner_icmp4->getNumAddresses() ) + return false; + if(sent_icmp4->getAddrEntrySize() != inner_icmp4->getAddrEntrySize()) + return false; + if(sent_icmp4->getLifetime() != inner_icmp4->getLifetime() ) + return false; + break; + + case ICMP_ROUTERSOLICIT: + /* Here we do not have much to compare, so we just test that + * the reserved field contains the same value, usually zero. */ + if(sent_icmp4->getReserved()!=inner_icmp4->getReserved()) + return false; + break; + + case ICMP_UNREACH: + case ICMP_SOURCEQUENCH: + case ICMP_TIMXCEED: + /* For these we cannot guarantee that the received ICMP error + * packet included data beyond the inner ICMP header, so we just + * assume that they are a match to the sent probe. (We shouldn't + * really be sending ICMP error messages and expect ICMP error + * responses that contain our ICMP error messages, should we? + * Well, even if we do, there is a good chance we are able to match + * those responses with the original probe) */ + break; + + case ICMP_REDIRECT: + if(sent_icmp4->getGatewayAddress().s_addr != inner_icmp4->getGatewayAddress().s_addr) + return false; + break; + + case ICMP_PARAMPROB: + if(sent_icmp4->getParameterPointer() != inner_icmp4->getParameterPointer()) + return false; + break; + + case ICMP_TRACEROUTE: + if(sent_icmp4->getIDNumber() != inner_icmp4->getIDNumber()) + return false; + if(sent_icmp4->getOutboundHopCount() != inner_icmp4->getOutboundHopCount()) + return false; + if(sent_icmp4->getOutputLinkSpeed() != inner_icmp4->getOutputLinkSpeed() ) + return false; + if(sent_icmp4->getOutputLinkMTU() != inner_icmp4->getOutputLinkMTU() ) + return false; + break; + + case ICMP_SECURITYFAILURES: + /* Check the pointer and the reserved field */ + if(sent_icmp4->getSecurityPointer() != inner_icmp4->getSecurityPointer()) + return false; + if(sent_icmp4->getReserved() != inner_icmp4->getReserved()) + return false; + break; + + default: + /* Do not match ICMP types we don't know about */ + return false; + break; + } + }else{ + return false; // Should never happen, though. + } + }else{ /* Received ICMP is informational. */ + + if(PKTPARSERDEBUG)printf("%s(): Received ICMP is an informational message.\n", __func__); + + /* If we get here it means that we received an informational ICMPv6 + * message. So now we have to check if the received message is the + * expected reply to the probe we sent (like an Echo reply for an Echo + * request, etc). */ + + if(sent_layer4->protocol_id()==HEADER_TYPE_ICMPv6 && rcvd_layer4->protocol_id()==HEADER_TYPE_ICMPv6){ + ICMPv6Header *sent_icmp6=(ICMPv6Header *)sent_layer4; + ICMPv6Header *rcvd_icmp6=(ICMPv6Header *)rcvd_layer4; + + switch( sent_icmp6->getType() ){ + + case ICMPv6_UNREACH: + case ICMPv6_TIMXCEED : + case ICMPv6_PKTTOOBIG: + case ICMPv6_PARAMPROB: + /* This should never happen. If we got here, the received type + * should be of an informational message, not an error message. */ + printf("Error in isResponse()\n"); + return false; + break; + + case ICMPv6_ECHO: + /* For Echo request, we expect echo replies */ + if(rcvd_icmp6->getType()!=ICMPv6_ECHOREPLY) + return false; + /* And we expect the ID and sequence number of the reply to + * match the ID and seq of the request. */ + if(sent_icmp6->getIdentifier() != rcvd_icmp6->getIdentifier()) + return false; + if(sent_icmp6->getSequence() != rcvd_icmp6->getSequence()) + return false; + break; + + case ICMPv6_ECHOREPLY: + /* We don't expect replies to Echo replies */ + return false; + break; + + case ICMPv6_ROUTERSOLICIT: + /* For Router solicitations, we expect Router advertisements. + * We only check if the received ICMP is a router advert because + * there is nothing else that can be used to match the solicitation + * with the response. */ + if(rcvd_icmp6->getType()!=ICMPv6_ROUTERADVERT) + return false; + break; + + case ICMPv6_ROUTERADVERT: + /* We don't expect replies to router advertisements */ + return false; + break; + + case ICMPv6_REDIRECT: + /* We don't expect replies to Redirect messages */ + return false; + break; + + case ICMPv6_NGHBRSOLICIT: + if(PKTPARSERDEBUG)printf("%s(): Sent ICMP is an ICMPv6 Neighbor Solicitation.\n", __func__); + /* For Neighbor solicitations, we expect Neighbor advertisements + * with the "S" flag set (solicited flag) and the same address + * in the "TargetAddress" field. */ + if(rcvd_icmp6->getType()!=ICMPv6_NGHBRADVERT) + return false; + if(PKTPARSERDEBUG)printf("%s(): Received ICMP is an ICMPv6 Neighbor Advertisement.\n", __func__); + if( !(rcvd_icmp6->getFlags() & 0x40) ) + return false; + if( memcmp(sent_icmp6->getTargetAddress().s6_addr, rcvd_icmp6->getTargetAddress().s6_addr, 16) !=0 ) + return false; + break; + + case ICMPv6_NGHBRADVERT: + /* We don't expect replies to Neighbor advertisements */ + return false; + break; + + case ICMPv6_NODEINFOQUERY: + /* For Node Information Queries we expect Node Information + * responses with the same Nonce value that we used in the query. */ + if(rcvd_icmp6->getType()!=ICMPv6_NODEINFORESP) + return false; + if( memcmp(sent_icmp6->getNonce(), rcvd_icmp6->getNonce(), NI_NONCE_LEN)!=0 ) + return false; + break; + + case ICMPv6_NODEINFORESP: + /* Obviously, we do not expect responses to a response */ + return false; + break; + + case ICMPv6_INVNGHBRSOLICIT: + /* For Inverse Neighbor Discovery Solicitations we expect + * advertisements in response. We don't do any additional + * validation since any advert can be considered a response + * to the solicitation. */ + if(rcvd_icmp6->getType()!=ICMPv6_INVNGHBRADVERT) + return false; + break; + + case ICMPv6_INVNGHBRADVERT: + /* We don't expect responses to advertisements */ + return false; + break; + + + case ICMPv6_RTRRENUM: + /* We don't expect specific responses to router renumbering + * messages. */ + return false; + break; + + case ICMPv6_GRPMEMBQUERY: + /* For Multicast Listener Discovery (MLD) queries, we expect + * either MLD Responses or MLD Done messages. We can't handle MLDv2 + * yet, so we don't match it. TODO: Implement support for MLDv2 */ + if(rcvd_icmp6->getType()!=ICMPv6_GRPMEMBREP && rcvd_icmp6->getType()!=ICMPv6_GRPMEMBRED) + return false; + /* Now we have two possibilities: + * a) The query is a "General Query" where the multicast address + * is set to zero. + * b) The query is a "Multicast-Address-Specific Query", where + * the multicast address field is set to an actual multicast + * address. + * In the first case, we match any query response to the request, + * as we don't have a multicast address to compare. In the second + * case, we verify that the target mcast address of the query + * matches the one in the response. */ + struct in6_addr zeroaddr; + memset(&zeroaddr, 0, sizeof(struct in6_addr)); + if( memcmp( sent_icmp6->getMulticastAddress().s6_addr, zeroaddr.s6_addr, 16) != 0 ){ /* Case B: */ + if (memcmp( sent_icmp6->getMulticastAddress().s6_addr, rcvd_icmp6->getMulticastAddress().s6_addr, 16)!=0 ) + return false; + } + break; + + case ICMPv6_GRPMEMBREP: + case ICMPv6_GRPMEMBRED: + /* We don't expect responses to MLD reports */ + return false; + break; + + case ICMPv6_MLDV2: + case ICMPv6_AGENTDISCOVREQ: + case ICMPv6_AGENTDISCOVREPLY: + case ICMPv6_MOBPREFIXSOLICIT: + case ICMPv6_MOBPREFIXADVERT: + case ICMPv6_CERTPATHSOLICIT: + case ICMPv6_CERTPATHADVERT: + case ICMPv6_EXPMOBILITY: + case ICMPv6_MRDADVERT: + case ICMPv6_MRDSOLICIT: + case ICMPv6_MRDTERMINATE: + case ICMPv6_FMIPV6: + default: + /* Do not match ICMPv6 types we don't implement or know about * + * TODO: Implement these ICMPv6 types. */ + return false; + break; + + } + + }else if(sent_layer4->protocol_id()==HEADER_TYPE_ICMPv4 && rcvd_layer4->protocol_id()==HEADER_TYPE_ICMPv4){ + ICMPv4Header *sent_icmp4=(ICMPv4Header *)sent_layer4; + ICMPv4Header *rcvd_icmp4=(ICMPv4Header *)rcvd_layer4; + + switch( sent_icmp4->getType() ){ + + case ICMP_ECHOREPLY: + /* We don't expect replies to Echo replies. */ + return false; + break; + + case ICMP_UNREACH: + case ICMP_SOURCEQUENCH: + case ICMP_REDIRECT: + case ICMP_TIMXCEED: + case ICMP_PARAMPROB: + /* Nodes are not supposed to respond to error messages, so + * we don't expect any replies. */ + return false; + break; + + case ICMP_ECHO: + /* For Echo request, we expect echo replies */ + if(rcvd_icmp4->getType()!=ICMP_ECHOREPLY) + return false; + /* And we expect the ID and sequence number of the reply to + * match the ID and seq of the request. */ + if(sent_icmp4->getIdentifier() != rcvd_icmp4->getIdentifier()) + return false; + if(sent_icmp4->getSequence() != rcvd_icmp4->getSequence()) + return false; + break; + + case ICMP_ROUTERSOLICIT: + /* For ICMPv4 router solicitations, we expect router advertisements. + * We don't validate anything else because in IPv4 any advert that + * comes from the host we sent the solicitation to can be + * considered a response. */ + if(rcvd_icmp4->getType()!=ICMP_ROUTERADVERT) + return false; + break; + + case ICMP_ROUTERADVERT: + /* We don't expect responses to advertisements */ + return false; + break; + + case ICMP_TSTAMP: + /* For Timestampt requests, we expect timestamp replies */ + if(rcvd_icmp4->getType()!=ICMP_TSTAMPREPLY) + return false; + /* And we expect the ID and sequence number of the reply to + * match the ID and seq of the request. */ + if(sent_icmp4->getIdentifier() != rcvd_icmp4->getIdentifier()) + return false; + if(sent_icmp4->getSequence() != rcvd_icmp4->getSequence()) + return false; + break; + + case ICMP_TSTAMPREPLY: + /* We do not expect responses to timestamp replies */ + return false; + break; + + case ICMP_INFO: + /* For Information requests, we expect Information replies */ + if(rcvd_icmp4->getType()!=ICMP_INFOREPLY) + return false; + /* And we expect the ID and sequence number of the reply to + * match the ID and seq of the request. */ + if(sent_icmp4->getIdentifier() != rcvd_icmp4->getIdentifier()) + return false; + if(sent_icmp4->getSequence() != rcvd_icmp4->getSequence()) + return false; + break; + + case ICMP_INFOREPLY: + /* We do not expect responses to Information replies */ + return false; + break; + + case ICMP_MASK: + /* For Netmask requests, we expect Netmask replies */ + if(rcvd_icmp4->getType()!=ICMP_MASKREPLY) + return false; + /* And we expect the ID and sequence number of the reply to + * match the ID and seq of the request. */ + if(sent_icmp4->getIdentifier() != rcvd_icmp4->getIdentifier()) + return false; + if(sent_icmp4->getSequence() != rcvd_icmp4->getSequence()) + return false; + break; + + case ICMP_MASKREPLY: + /* We do not expect responses to netmask replies */ + return false; + break; + + case ICMP_TRACEROUTE: + /* We don't expect replies to a traceroute message as it is + * sent as a response to an IP datagram that contains the + * IP traceroute option. Also, note that this function does + * not take this into account when processing IPv4 datagrams + * so if we receive an ICMP_TRACEROUTE we'll not be able + * to match it with the original IP datagram. */ + return false; + break; + + case ICMP_DOMAINNAME: + /* For Domain Name requests, we expect Domain Name replies */ + if(rcvd_icmp4->getType()!=ICMP_DOMAINNAMEREPLY) + return false; + /* And we expect the ID and sequence number of the reply to + * match the ID and seq of the request. */ + if(sent_icmp4->getIdentifier() != rcvd_icmp4->getIdentifier()) + return false; + if(sent_icmp4->getSequence() != rcvd_icmp4->getSequence()) + return false; + break; + + case ICMP_DOMAINNAMEREPLY: + /* We do not expect replies to DN replies */ + return false; + break; + + case ICMP_SECURITYFAILURES: + /* Nodes are not expected to send replies to this message, as it + * is an ICMP error. */ + return false; + break; + } + }else{ + return false; // Should never happen + } + } + }else if(sent_layer4->protocol_id()==HEADER_TYPE_TCP || sent_layer4->protocol_id()==HEADER_TYPE_UDP){ + + if(PKTPARSERDEBUG)printf("%s(): Sent packet has a transport layer header.\n", __func__); + + /* Both are TCP or both UDP */ + if(sent_layer4->protocol_id()==rcvd_layer4->protocol_id()){ + + if(PKTPARSERDEBUG)printf("%s(): Received packet has a transport layer header too.\n", __func__); + + /* Probe source port must equal response target port */ + if( ((TransportLayerElement *)sent_layer4)->getSourcePort() != ((TransportLayerElement *)rcvd_layer4)->getDestinationPort() ) + return false; + /* Probe target port must equal response source port */ + if( ((TransportLayerElement *)rcvd_layer4)->getSourcePort() != ((TransportLayerElement *)sent_layer4)->getDestinationPort() ) + return false; + + /* If we sent TCP or UDP and got ICMP in response, we need to find a copy of our packet in the + * ICMP payload, providing it is an ICMP error message. */ + }else if(rcvd_layer4->protocol_id()==HEADER_TYPE_ICMPv6 || rcvd_layer4->protocol_id()==HEADER_TYPE_ICMPv4){ + + if(PKTPARSERDEBUG)printf("%s(): Received packet does not have transport layer header but an ICMP header.\n", __func__); + + /* We only expect ICMP error messages */ + if( !(((ICMPHeader *)rcvd_layer4)->isError()) ) + return false; + + /* Let's validate the original header */ + NetworkLayerElement *iperror=(NetworkLayerElement *)rcvd_layer4->getNextElement(); + + /* ICMP error message must contain the original datagram */ + if(iperror==NULL) + return false; + + /* The first header must be IP */ + if(iperror->protocol_id()!=HEADER_TYPE_IPv6 && iperror->protocol_id()!=HEADER_TYPE_IPv4) + return false; + + /* The IP version must match the probe's */ + if(iperror->protocol_id()!=sent_ip->protocol_id()) + return false; + + /* Source and destination addresses must match the probe's (NATs are + * supposed to rewrite them too, so this should be OK) */ + if( memcmp(iperror->getSourceAddress(), sent_ip->getSourceAddress(), iperror->getAddressLength())!=0 ) + return false; + if( memcmp(iperror->getDestinationAddress(), sent_ip->getDestinationAddress(), iperror->getAddressLength())!=0 ) + return false; + + /* So far we've verified that the ICMP error contains an IP datagram that matches + * what we sent. Now, let's find the upper layer protocol (skip extension + * headers and the like until we find some transport protocol). */ + TransportLayerElement *layer4error=(TransportLayerElement *)iperror->getNextElement(); + while(layer4error!=NULL){ + if(layer4error->protocol_id()==HEADER_TYPE_UDP || layer4error->protocol_id()==HEADER_TYPE_TCP ){ + break; + }else{ + layer4error=(TransportLayerElement *)layer4error->getNextElement(); + } + } + if(layer4error==NULL) + return false; + + /* Now make sure we see the same port numbers */ + if( layer4error->getSourcePort() != ((TransportLayerElement *)sent_layer4)->getSourcePort() ) + return false; + if( layer4error->getDestinationPort() != ((TransportLayerElement *)sent_layer4)->getDestinationPort() ) + return false; + } else { + return false; + } + }else{ + /* We sent a layer 4 other than ICMP, ICMPv6, TCP, or UDP. We return false + * as we cannot match responses for protocols we don't understand */ + return false; + } + + /* If we get there it means the packet passed all the tests. Return true + * to indicate that the packet is a response to this FPProbe. */ + if(PKTPARSERDEBUG)printf("%s(): The received packet was successfully matched with the sent packet.\n", __func__); + return true; +} diff --git a/libnetutil/PacketParser.h b/libnetutil/PacketParser.h new file mode 100644 index 0000000000..60f42c09f4 --- /dev/null +++ b/libnetutil/PacketParser.h @@ -0,0 +1,162 @@ + +/*************************************************************************** + * PacketParser.h -- The PacketParser Class offers methods to parse * + * received network packets. Its main purpose is to facilitate the * + * conversion of raw sequences of bytes into chains of objects of the * + * PacketElement family. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2010 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#ifndef __PACKETPARSER_H__ +#define __PACKETPARSER_H__ 1 + +#include "ApplicationLayerElement.h" +#include "ARPHeader.h" +#include "DataLinkLayerElement.h" +#include "EthernetHeader.h" +#include "ICMPHeader.h" +#include "ICMPv4Header.h" +#include "ICMPv6Header.h" +#include "ICMPv6Option.h" +#include "ICMPv6RRBody.h" +#include "IPv4Header.h" +#include "IPv6Header.h" +#include "NetworkLayerElement.h" +#include "PacketElement.h" +#include "RawData.h" +#include "TCPHeader.h" +#include "TransportLayerElement.h" +#include "UDPHeader.h" +#include "HopByHopHeader.h" +#include "DestOptsHeader.h" +#include "FragmentHeader.h" +#include "RoutingHeader.h" + + +#define LINK_LAYER 2 +#define NETWORK_LAYER 3 +#define TRANSPORT_LAYER 4 +#define APPLICATION_LAYER 5 +#define EXTHEADERS_LAYER 6 + +typedef struct header_type_string{ + u32 type; + const char *str; +}header_type_string_t; + + +typedef struct packet_type{ + u32 type; + u32 length; +}pkt_type_t; + + +class PacketParser { + + private: + + public: + + /* Misc */ + PacketParser(); + ~PacketParser(); + void reset(); + + static const char *header_type2string(int val); + static pkt_type_t *parse_packet(const u8 *pkt, size_t pktlen, bool eth_included); + static int dummy_print_packet_type(const u8 *pkt, size_t pktlen, bool eth_included); /* TODO: remove */ + static int dummy_print_packet(const u8 *pkt, size_t pktlen, bool eth_included); /* TODO: remove */ + static int payload_offset(const u8 *pkt, size_t pktlen, bool link_included); + static PacketElement *split(const u8 *pkt, size_t pktlen, bool eth_included); + static PacketElement *split(const u8 *pkt, size_t pktlen); + static int freePacketChain(PacketElement *first); + static const char *test_packet_parser(PacketElement *test_pkt); + static bool is_response(PacketElement *sent, PacketElement *rcvd); + +}; /* End of class PacketParser */ + +#endif /* __PACKETPARSER_H__ */ diff --git a/libnetutil/RawData.cc b/libnetutil/RawData.cc new file mode 100644 index 0000000000..c17e80ede6 --- /dev/null +++ b/libnetutil/RawData.cc @@ -0,0 +1,211 @@ + +/*************************************************************************** + * RawData.cc -- The RawData Class represents a network packet payload. It * + * is essentially a single buffer that may contain either random data or * + * caller supplied data. This class can be used, for example, to be linked * + * to a UDP datagram. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#include "RawData.h" + +/******************************************************************************/ +/* CONTRUCTORS, DESTRUCTORS AND INITIALIZATION METHODS */ +/******************************************************************************/ +RawData::RawData(){ + this->reset(); +} /* End of RawData contructor */ + + +RawData::~RawData(){ + if(this->data!=NULL){ + free(this->data); + this->data=NULL; + } +} /* End of RawData destructor */ + + +/** Sets every attribute to its default value */ +void RawData::reset(){ + this->data=NULL; + this->length=0; +} /* End of reset() */ + + +/******************************************************************************/ +/* PacketElement:: OVERWRITTEN METHODS */ +/******************************************************************************/ + +u8 * RawData::getBufferPointer(){ + return this->getBufferPointer(NULL); +} /* End of getBufferPointer() */ + + +u8 * RawData::getBufferPointer(int *mylen){ + if(mylen!=NULL) + *mylen=this->length; + return this->data; +} /* End of getBufferPointer() */ + + +/** Added for consistency with the rest of classes of the PacketElement family. */ +int RawData::storeRecvData(const u8 *buf, size_t len){ + return this->store(buf, len); +} /* End of storeRecvData() */ + + +/* Returns a protocol identifier. This is used by packet parsing funtions + * that return linked lists of PacketElement objects, to determine the protocol + * the object represents. */ +int RawData::protocol_id() const { + return HEADER_TYPE_RAW_DATA; +} /* End of protocol_id() */ + + +/** Determines if the data stored in the object after an storeRecvData() call + * is valid and safe to use. This mainly checks the length of the data but may + * also test the value of certain protocol fields to ensure their correctness. + * @return the length, in bytes, of the header, if its found to be valid or + * OP_FAILURE (-1) otherwise. */ +int RawData::validate(){ + return this->length; +} /* End of validate() */ + + +/** Prints the contents of the header and calls print() on the next protocol + * header in the chain (if there is any). + * @return OP_SUCCESS on success and OP_FAILURE in case of error. */ +int RawData::print(FILE *output, int detail) const { + + if(detail<=PRINT_DETAIL_MED){ + fprintf(output, "Data["); + fprintf(output, "%d byte%s]", this->length, (this->length!=1)? "s":""); + }else{ + // Print hex dump + fprintf(output, "Data[--HEXDUMP-- %d byte%s]", this->length, (this->length!=1)? "s":""); + // @todo UNIMPLEMENTED. I don't want to use libnetutil's print_hexdump() + // here because it introduces dependencies. + } + if(this->next!=NULL){ + print_separator(output, detail); + next->print(output, detail); + } + return OP_SUCCESS; +} /* End of print() */ + + +/******************************************************************************/ +/* PROTOCOL-SPECIFIC METHODS */ +/******************************************************************************/ + +int RawData::store(const u8 *buf, size_t len){ + /* If buffer had already been set, try to reuse it. */ + if(this->data!=NULL){ + if( this->length >= (int)len ){ + memcpy(this->data, buf, len); + this->length=(int)len; + return OP_SUCCESS; + }else{ + free(this->data); + } + } + if( (this->data=(u8 *)calloc(len, sizeof(u8)))==NULL ) + return OP_FAILURE; + memcpy(this->data, buf, len); + this->length=(int)len; + return OP_SUCCESS; +} /* End of store() */ + + +int RawData::store(const char *str){ + if(str==NULL) + return OP_FAILURE; + else + return this->store((const u8*)str, strlen(str)); +} /* End of store() */ + + diff --git a/libnetutil/RawData.h b/libnetutil/RawData.h new file mode 100644 index 0000000000..201a74c014 --- /dev/null +++ b/libnetutil/RawData.h @@ -0,0 +1,121 @@ + +/*************************************************************************** + * RawData.h -- The RawData Class represents a network packet payload. It * + * is essentially a single buffer that may contain either random data or * + * caller supplied data. This class can be used, for example, to be linked * + * to a UDP datagram. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#ifndef RAWDATA_H +#define RAWDATA_H 1 + +#include "ApplicationLayerElement.h" + + +class RawData : public ApplicationLayerElement { + + private: + u8 *data; + + public: + RawData(); + ~RawData(); + void reset(); + u8 *getBufferPointer(); + int storeRecvData(const u8 *buf, size_t len); + int protocol_id() const; + int validate(); + int print(FILE *output, int detail) const; + + u8 *getBufferPointer(int *mylen); + int store(const u8 *buf, size_t len); + int store(const char *str); + +}; + +#endif diff --git a/libnetutil/RoutingHeader.cc b/libnetutil/RoutingHeader.cc new file mode 100644 index 0000000000..b7a35c45fe --- /dev/null +++ b/libnetutil/RoutingHeader.cc @@ -0,0 +1,340 @@ + +/*************************************************************************** + * RoutingHeader.cc -- The RoutingHeader Class represents an IPv6 Routing * + * extension header. * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#include "RoutingHeader.h" +#include + +/******************************************************************************/ +/* CONTRUCTORS, DESTRUCTORS AND INITIALIZATION METHODS */ +/******************************************************************************/ +RoutingHeader::RoutingHeader() { + this->reset(); +} /* End of RoutingHeader constructor */ + + +RoutingHeader::~RoutingHeader() { + +} /* End of RoutingHeader destructor */ + + +/** Sets every attribute to its default value */ +void RoutingHeader::reset(){ + memset(&this->h, 0, sizeof(nping_ipv6_ext_routing_hdr_t)); + this->length=ROUTING_HEADER_MIN_LEN; + this->curr_addr=(u8 *)this->h.data; +} /* End of reset() */ + + +/******************************************************************************/ +/* PacketElement:: OVERWRITTEN METHODS */ +/******************************************************************************/ + +/** @warning This method is essential for the superclass getBinaryBuffer() + * method to work. Do NOT change a thing unless you know what you're doing */ +u8 *RoutingHeader::getBufferPointer(){ + return (u8*)(&this->h); +} /* End of getBufferPointer() */ + + +/** Stores supplied packet in the internal buffer so the information + * can be accessed using the standard get & set methods. + * @warning The RoutingHeader class is able to hold a maximum of + * sizeof(nping_icmpv6_hdr_t) bytes. If the supplied buffer is longer than + * that, only the first 1508 bytes will be stored in the internal buffer. + * @warning Supplied len MUST be at least 8 bytes (min ICMPv6 header length). + * @return OP_SUCCESS on success and OP_FAILURE in case of error */ +int RoutingHeader::storeRecvData(const u8 *buf, size_t len){ + if(buf==NULL || lenlength=0; + return OP_FAILURE; + }else{ + /* Store the first 4 bytes, so we can access lenght and routing type */ + memcpy(&(this->h), buf, 4); + + /* Our behaviour is different depending on the routing type. */ + switch(this->h.type){ + + /* Routing Type 0 (deprecated by RFC 5095)*/ + case 0: + /* Type 0 has a variable length, but the value of its HdrExtLen + * field must be even (because it must be a multiple of the + * IPv6 address size). We also make sure that the received buffer + * has as many bytes as the HdrExtLen field says it has, and + * that it doesn't exceed the maximum number of octets we + * can store in this object. */ + if(this->h.len%2==1 || ((unsigned int)(this->h.len+1))*8 > len || (this->h.len+1)*8 > ROUTING_HEADER_MAX_LEN){ + this->length=0; + return OP_FAILURE; + }else{ + int pkt_len=(this->h.len+1)*8; + this->reset(); + this->length=pkt_len; + memcpy(&(this->h), buf, this->length); + return OP_SUCCESS; + } + break; + + /* Routing Type 2 (For IPv6 Mobility. See RFC 6275) */ + case 2: + /* Type 2 has a fixed length. If we have that many octets, store + * them. We'll perform validation later in validate(). */ + if(lenlength=0; + return OP_FAILURE; + }else{ + this->reset(); + memcpy(&(this->h), buf, ROUTING_TYPE_2_HEADER_LEN); + this->length=ROUTING_TYPE_2_HEADER_LEN; + return OP_SUCCESS; + } + break; + + /* Unknown routing type */ + default: + /* If this is some routing type that we don't know about, we'll have + * to store as much data as the header says it has. Obvioulsy, we + * check that we received as much data as the HdrExtLen advertises, + * and that we don't exceed our own internal limit. */ + if( ((unsigned int)(this->h.len+1))*8 > len || (this->h.len+1)*8 > ROUTING_HEADER_MAX_LEN){ + this->length=0; + return OP_FAILURE; + }else{ + this->reset(); + this->length=(this->h.len+1)*8; + memcpy(&(this->h), buf, this->length); + return OP_SUCCESS; + } + break; + } + } + return OP_FAILURE; +} /* End of storeRecvData() */ + + +/* Returns a protocol identifier. This is used by packet parsing funtions + * that return linked lists of PacketElement objects, to determine the protocol + * the object represents. */ +int RoutingHeader::protocol_id() const { + return HEADER_TYPE_IPv6_ROUTE; +} /* End of protocol_id() */ + + +/** Determines if the data stored in the object after an storeRecvData() call + * is valid and safe to use. This mainly checks the length of the data but may + * also test the value of certain protocol fields to ensure their correctness. + * @return the length, in bytes, of the header, if its found to be valid or + * OP_FAILURE (-1) otherwise. */ +int RoutingHeader::validate(){ + + /* Check the object's length makes sense*/ + if(this->length < ROUTING_HEADER_MIN_LEN || this->length%8!=0) { + return OP_FAILURE; + } + + switch(this->h.type){ + /* Routing Type 0 (deprecated by RFC 5095)*/ + case 0: + /* Here we check that: + * 1) The length in HdrExtLen is even. + * 2) The length in HdrExtLen matches the octects stored in this object. + * 3) The length in HdrExtLen does not exceed our internal limit. */ + if(this->h.len%2==1 || (this->h.len+1)*8 != this->length || (this->h.len+1)*8 > ROUTING_HEADER_MAX_LEN){ + return OP_FAILURE; + } + + /* Also, for Type 0, the value in the SegmentsLeft field should be less + * than or equal to the number of addresses in the packet. We verify + * that using the value of the HDrExtLen field which, divided by two, + * yields the number of addresses in the packet. It certainly doesn't + * make sense for the packet to say there are 5 hops left when we + * have less than 5 IPv6 addresses. We allow it to be less than + * the number of addresses present in the packet because the RFC 2460 + * only talkes about segleft being greater than HDrExtLen/2, not less. */ + if(this->h.segleft > this->h.len/2){ + return OP_FAILURE; + } + break; + + /* Routing Type 2 (For IPv6 Mobility. See RFC 6275) */ + case 2: + /* Check that we have the exact number of octets we expect. */ + if(this->length!= ROUTING_TYPE_2_HEADER_LEN){ + return OP_FAILURE; + } + /* Also check that the HdrExtLen and SegmentsLeft fields have the + * value that RFC 6275 dictates. */ + if(this->h.segleft!=1 || this->h.len!=2){ + return OP_FAILURE; + } + break; + + /* Unknown routing type */ + default: + /* If this is some routing type that we don't know about, we just + * check that the length makes sense because we cannot make assumptions + * about the semantics of other fields. */ + if( this->length!=(this->h.len+1)*8 || (this->h.len+1)*8>ROUTING_HEADER_MAX_LEN){ + return OP_FAILURE; + } + break; + + } + return this->length; +} /* End of validate() */ + + +/** Prints the contents of the header and calls print() on the next protocol + * header in the chain (if there is any). + * @return OP_SUCCESS on success and OP_FAILURE in case of error. */ +int RoutingHeader::print(FILE *output, int detail) const { + fprintf(output, "Routing[nh=%d len=%d type=%d segleft=%d]", this->h.nh, this->h.len, this->h.type, this->h.segleft); + // TODO: @todo : Implement this + if(this->next!=NULL){ + print_separator(output, detail); + next->print(output, detail); + } + return OP_SUCCESS; +} /* End of print() */ + + +/******************************************************************************/ +/* PROTOCOL-SPECIFIC METHODS */ +/******************************************************************************/ + +/** Set Next Header field */ +int RoutingHeader::setNextHeader(u8 val){ + this->h.nh = val; + return OP_SUCCESS; +} /* End of setNextHeader() */ + + +/** Returns next header id */ +u8 RoutingHeader::getNextHeader(){ + return this->h.nh; +} /* End of getNextHeader() */ + + +/** Set routing type */ +int RoutingHeader::setRoutingType(u8 val){ + this->h.type = val; + return OP_SUCCESS; +} /* End of setRoutingType() */ + + +/** Returns the routing type */ +u8 RoutingHeader::getRoutingType(){ + return this->h.type; +} /* End of getRoutingType() */ + + +/** Set number of segments left */ +int RoutingHeader::setSegmentsLeft(u8 val){ + this->h.segleft = val; + return OP_SUCCESS; +} /* End of setSegmentsLeft() */ + + +/** Returns the number of segments left */ +u8 RoutingHeader::getSegmentsLeft(){ + return this->h.segleft; +} /* End of getSegmentsLeft() */ + + +/** Set number of segments left */ +int RoutingHeader::addAddress(struct in6_addr val){ + /* Check we don't exceed max length */ + if((this->length + 16)>ROUTING_HEADER_MAX_LEN) + return OP_FAILURE; + memcpy(this->curr_addr, val.s6_addr, 16); + this->curr_addr+=16; + this->h.len+=2; + this->length+=16; + return OP_SUCCESS; +} /* End of setSegmentsLeft() */ diff --git a/libnetutil/RoutingHeader.h b/libnetutil/RoutingHeader.h new file mode 100644 index 0000000000..e979cf2bab --- /dev/null +++ b/libnetutil/RoutingHeader.h @@ -0,0 +1,207 @@ + +/*************************************************************************** + * RoutingHeader.h -- The RoutingHeader Class represents an IPv6 Routing * + * extension header. * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#ifndef __ROUTING_HEADER_H__ +#define __ROUTING_HEADER_H__ 1 + +#include "IPv6ExtensionHeader.h" + +#define ROUTING_HEADER_MIN_LEN 8 +#define ROUTING_HEADER_MAX_LEN (8 + 256*8) +#define ROUTING_MAX_DATA_LEN 256*8 +#define ROUTING_TYPE_2_HEADER_LEN 24 +#define ROUTING_TYPE_0_MIN_LEN 8 + +class RoutingHeader : public IPv6ExtensionHeader { + + private: + + /* + 1) Generic Routing Header: + + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Next Header | Hdr Ext Len | Routing Type | Segments Left | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + . . + . type-specific data . + . . + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + 2) Type 0 Routing header: + + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Next Header | Hdr Ext Len | Routing Type=0| Segments Left | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Reserved | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + + + | | + + Address[1] + + | | + + + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + + + | | + + Address[2] + + | | + + + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + . . . + . . . + . . . + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + + + | | + + Address[n] + + | | + + + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + 3) Type 2 Routing header: + + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Next Header | Hdr Ext Len=2 | Routing Type=2|Segments Left=1| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Reserved | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + + + | | + + Home Address + + | | + + + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + struct nping_ipv6_ext_routing_hdr{ + u8 nh; + u8 len; + u8 type; + u8 segleft; + u32 reserved; + u8 data[ROUTING_MAX_DATA_LEN]; + }__attribute__((__packed__)); + typedef struct nping_ipv6_ext_routing_hdr nping_ipv6_ext_routing_hdr_t; + + nping_ipv6_ext_routing_hdr_t h; + u8 *curr_addr; + + public: + RoutingHeader(); + ~RoutingHeader(); + void reset(); + u8 *getBufferPointer(); + int storeRecvData(const u8 *buf, size_t len); + int protocol_id() const; + int validate(); + int print(FILE *output, int detail) const; + + /* Protocol specific methods */ + int setNextHeader(u8 val); + u8 getNextHeader(); + + int setRoutingType(u8 val); + u8 getRoutingType(); + + int setSegmentsLeft(u8 val); + u8 getSegmentsLeft(); + + int addAddress(struct in6_addr val); + +}; /* End of class RoutingHeader */ + +#endif diff --git a/libnetutil/TCPHeader.cc b/libnetutil/TCPHeader.cc new file mode 100644 index 0000000000..7be518fb4d --- /dev/null +++ b/libnetutil/TCPHeader.cc @@ -0,0 +1,963 @@ + +/*************************************************************************** + * TCPHeader.cc -- The TCPHeader Class represents a TCP packet. It * + * contains methods to set the different header fields. These methods * + * tipically perform the necessary error checks and byte order * + * conversions. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#include "TCPHeader.h" +#include +/******************************************************************************/ +/* CONTRUCTORS, DESTRUCTORS AND INITIALIZATION METHODS */ +/******************************************************************************/ +TCPHeader::TCPHeader(){ + this->reset(); +} /* End of TCPHeader constructor */ + + +TCPHeader::~TCPHeader(){ + +} /* End of TCPHeader destructor */ + +/** Sets every attribute to its default value */ +void TCPHeader::reset(){ + memset(&this->h, 0, sizeof(nping_tcp_hdr_t)); + this->length=TCP_HEADER_LEN; /* Initial value 20. This will be incremented if options are used */ + this->tcpoptlen=0; + this->setSourcePort(TCP_DEFAULT_SPORT); + this->setDestinationPort(TCP_DEFAULT_DPORT); + this->setSeq(TCP_DEFAULT_SEQ); + this->setAck(TCP_DEFAULT_ACK); + this->setFlags(TCP_DEFAULT_FLAGS); + this->setWindow(TCP_DEFAULT_WIN); + this->setUrgPointer(TCP_DEFAULT_URP); + this->setOffset(); +} /* End of reset() */ + + +/******************************************************************************/ +/* PacketElement:: OVERWRITTEN METHODS */ +/******************************************************************************/ + +/** @warning This method is essential for the superclass getBinaryBuffer() + * method to work. Do NOT change a thing unless you know what you're doing */ +u8 * TCPHeader::getBufferPointer(){ + return (u8*)(&h); +} /* End of getBufferPointer() */ + + +/** Stores supplied packet in the internal buffer so the information + * can be accessed using the standard get & set methods. + * @warning The TCPHeader class is able to hold a maximum of 60 bytes. If the + * supplied buffer is longer than that, only the first 60 bytes will be stored + * in the internal buffer. + * @warning Supplied len MUST be at least 20 bytes (min TCP header length). + * @return OP_SUCCESS on success and OP_FAILURE in case of error */ +int TCPHeader::storeRecvData(const u8 *buf, size_t len){ + if(buf==NULL || lenreset(); /* Re-init the object, just in case the caller had used it already */ + this->length=stored_len; + if(stored_len>TCP_HEADER_LEN) + this->tcpoptlen=stored_len-TCP_HEADER_LEN; + memcpy(&(this->h), buf, stored_len); + } + return OP_SUCCESS; +} /* End of storeRecvData() */ + + +/* Returns a protocol identifier. This is used by packet parsing funtions + * that return linked lists of PacketElement objects, to determine the protocol + * the object represents. */ +int TCPHeader::protocol_id() const { + return HEADER_TYPE_TCP; +} /* End of protocol_id() */ + + +/** Determines if the data stored in the object after an storeRecvData() call + * is valid and safe to use. This mainly checks the length of the data but may + * also test the value of certain protocol fields to ensure their correctness. + * @warning If the information stored in the object has been set through a + * call to storeRecvData(), the object's internal length count may be updated + * if the validation is successful. + * @return the length, in bytes, of the header, if its found to be valid or + * OP_FAILURE (-1) otherwise. */ +int TCPHeader::validate(){ + if(this->getOffset()<5) + return OP_FAILURE; + else if(this->getOffset()*4 > this->length) + return OP_FAILURE; + this->length=this->getOffset()*4; + return this->length; +} /* End of validate() */ + + +/** Prints the contents of the header and calls print() on the next protocol + * header in the chain (if there is any). + * @return OP_SUCCESS on success and OP_FAILURE in case of error. */ +int TCPHeader::print(FILE *output, int detail) const { + char optinfo[256]; + fprintf(output, "TCP["); + fprintf(output, "%d", this->getSourcePort()); + fprintf(output, " >"); + fprintf(output, " %d", this->getDestinationPort()); + fprintf(output, " %s%s%s%s%s%s%s%s", + !this->getSYN() ? "" : "S", + !this->getFIN() ? "" : "F", + !this->getRST() ? "" : "R", + !this->getPSH() ? "" : "P", + !this->getACK() ? "" : "A", + !this->getURG() ? "" : "U", + !this->getECN() ? "" : "E", + !this->getCWR() ? "" : "C" + ); + fprintf(output, " seq=%lu", (long unsigned int)this->getSeq() ); + if(detail>=PRINT_DETAIL_HIGH){ + fprintf(output, " ack=%lu", (long unsigned int)this->getAck() ); + fprintf(output, " off=%d", this->getOffset() ); + fprintf(output, " res=%d", this->h.th_x2); + } + fprintf(output, " win=%hu", this->getWindow() ); + if(detail>=PRINT_DETAIL_MED) + fprintf(output, " csum=0x%04X", ntohs( this->getSum() )); + if(detail>=PRINT_DETAIL_HIGH) + fprintf(output, " urp=%d", this->getUrgPointer() ); + + if(this->tcpoptlen>0 && (this->length >= TCP_HEADER_LEN+this->tcpoptlen) && this->tcpoptlen<=MAX_TCP_OPTIONS_LEN){ + this->__tcppacketoptinfo(this->h.options, this->tcpoptlen, optinfo, sizeof(optinfo)-1); + optinfo[255]='\0'; + fprintf(output, " %s", optinfo); + } + fprintf(output, "]"); + + if(this->next!=NULL){ + print_separator(output, detail); + next->print(output, detail); + } + return OP_SUCCESS; +} /* End of print() */ + + +/* Get an ASCII information about a tcp option which is pointed by + optp, with a length of len. The result is stored in the result + buffer. The result may look like "" */ +void TCPHeader::__tcppacketoptinfo(const u8 *optp, int len, char *result, int bufsize) const { + assert(optp); + assert(result); + char *p, ch; + const u8 *q; + int opcode; + u16 tmpshort; + u32 tmpword1, tmpword2; + unsigned int i=0; + + p = result; + *p = '\0'; + q = optp; + ch = '<'; + + while (len > 0 && bufsize > 2) { + Snprintf(p, bufsize, "%c", ch); + bufsize--; + p++; + opcode = *q++; + if (!opcode) { /* End of List */ + + Snprintf(p, bufsize, "eol"); + bufsize -= strlen(p); + p += strlen(p); + + len--; + + } else if (opcode == 1) { /* No Op */ + Snprintf(p, bufsize, "nop"); + bufsize -= strlen(p); + p += strlen(p); + + len--; + } else if (opcode == 2) { /* MSS */ + if (len < 4) + break; /* MSS has 4 bytes */ + + q++; + memcpy(&tmpshort, q, 2); + + Snprintf(p, bufsize, "mss %u", ntohs(tmpshort)); + bufsize -= strlen(p); + p += strlen(p); + + q += 2; + len -= 4; + } else if (opcode == 3) { /* Window Scale */ + if (len < 3) + break; /* Window Scale option has 3 bytes */ + + q++; + + Snprintf(p, bufsize, "wscale %u", *q); + bufsize -= strlen(p); + p += strlen(p); + + q++; + len -= 3; + } else if (opcode == 4) { /* SACK permitted */ + if (len < 2) + break; /* SACK permitted option has 2 bytes */ + + Snprintf(p, bufsize, "sackOK"); + bufsize -= strlen(p); + p += strlen(p); + + q++; + len -= 2; + } else if (opcode == 5) { /* SACK */ + unsigned sackoptlen = *q; + if ((unsigned) len < sackoptlen) + break; + + /* This would break parsing, so it's best to just give up */ + if (sackoptlen < 2) + break; + + q++; + + if ((sackoptlen - 2) == 0 || ((sackoptlen - 2) % 8 != 0)) { + Snprintf(p, bufsize, "malformed sack"); + bufsize -= strlen(p); + p += strlen(p); + } else { + Snprintf(p, bufsize, "sack %d ", (sackoptlen - 2) / 8); + bufsize -= strlen(p); + p += strlen(p); + for (i = 0; i < sackoptlen - 2; i += 8) { + memcpy(&tmpword1, q + i, 4); + memcpy(&tmpword2, q + i + 4, 4); + Snprintf(p, bufsize, "{%u:%u}", tmpword1, tmpword2); + bufsize -= strlen(p); + p += strlen(p); + } + } + + q += sackoptlen - 2; + len -= sackoptlen; + } else if (opcode == 8) { /* Timestamp */ + if (len < 10) + break; /* Timestamp option has 10 bytes */ + + q++; + memcpy(&tmpword1, q, 4); + memcpy(&tmpword2, q + 4, 4); + + Snprintf(p, bufsize, "timestamp %u %u", ntohl(tmpword1), + ntohl(tmpword2)); + bufsize -= strlen(p); + p += strlen(p); + + q += 8; + len -= 10; + } + + ch = ','; + } + + if (len > 0) { + *result = '\0'; + return; + } + + Snprintf(p, bufsize, ">"); +} + + + +/******************************************************************************/ +/* PROTOCOL-SPECIFIC METHODS */ +/******************************************************************************/ + +/** Sets source port. + * @warning Port must be supplied in host byte order. This method performs + * byte order conversion using htons() */ +int TCPHeader::setSourcePort(u16 p){ + h.th_sport = htons(p); + return OP_SUCCESS; +} /* End of setSourcePort() */ + + +/** Returns source port in HOST byte order */ +u16 TCPHeader::getSourcePort() const { + return ntohs(h.th_sport); +} /* End of getSourcePort() */ + + +/** Sets destination port. + * @warning Port must be supplied in host byte order. This method performs + * byte order conversion using htons() */ +int TCPHeader::setDestinationPort(u16 p){ + h.th_dport = htons(p); + return OP_SUCCESS; +} /* End of setDestinationPort() */ + + +/** Returns destination port in HOST byte order */ +u16 TCPHeader::getDestinationPort() const { + return ntohs(h.th_dport); +} /* End of getDestinationPort() */ + + +/** Sets sequence number. + * @warning Seq number must be supplied in host byte order. This method + * performs byte order conversion using htonl() */ +int TCPHeader::setSeq(u32 p){ + h.th_seq = htonl(p); + return OP_SUCCESS; +} /* End of setSeq() */ + + +/** Returns sequence number in HOST byte order */ +u32 TCPHeader::getSeq() const { + return ntohl(h.th_seq); +} /* End of getSeq() */ + + +/** Sets acknowledgement number. + * @warning ACK number must be supplied in host byte order. This method + * performs byte order conversion using htonl() */ +int TCPHeader::setAck(u32 p){ + h.th_ack = htonl(p); + return OP_SUCCESS; +} /* End of setAck() */ + + +/** Returns ACK number in HOST byte order */ +u32 TCPHeader::getAck() const { + return ntohl(h.th_ack); +} /* End of getAck() */ + + +/* TODO: Test this method. It may not work becuasse th_off is supposed to + * be 4 bits long and arg o is 8. + * UPDATE: It seems to work just fine. However, let's keep this note just + * in case problems arise. */ +int TCPHeader::setOffset(u8 o){ + h.th_off = o; + return OP_SUCCESS; +} /* End of setOffset() */ + + +int TCPHeader::setOffset(){ + h.th_off = 5 + tcpoptlen/4; + return OP_SUCCESS; +} /* End of setOffset() */ + + +/** Returns offset value */ +u8 TCPHeader::getOffset() const { + return h.th_off; +} /* End of getOffset() */ + + +/* Sets the 4-bit reserved field (Note that there are not 4 reserved bits anymore + * as RFC 3540 introduces a new TCP flag, so calling this will overwrite + * the value of such flag. */ +int TCPHeader::setReserved(u8 r){ + h.th_x2 = r; + return OP_SUCCESS; +} + + +u8 TCPHeader::getReserved() const { + return h.th_x2; +} + + +/** Sets TCP flags */ +int TCPHeader::setFlags(u8 f){ + h.th_flags = f; + return OP_SUCCESS; +} /* End of setFlags() */ + + +/** Returns the 8bit flags field of the TCP header */ +u8 TCPHeader::getFlags() const { + return h.th_flags; +} /* End of getFlags() */ + + +/* Returns the 16bit flags field of the TCP header. As RFC 3540 defines a new + * flag (NS), we no longer can store all TCP flags in a single octet, so + * this method returns the flags as a two-octet unsigned integer. */ +u16 TCPHeader::getFlags16() const { + /* Obtain the value of dataoff+reserved+flags in host byte order */ + u16 field=ntohs(*(u16 *)(((u8 *)&this->h)+12)); + /* Erase the contents of the data offset field */ + field = field & 0x0FFF; + return field; +} /* End of getFlags16() */ + + +/** Sets flag CWR + * @return Previous state of the flag */ +bool TCPHeader::setCWR(){ + u8 prev = h.th_flags & TH_CWR; + h.th_flags |= TH_CWR; + return prev; +} /* End of setCWR() */ + + +/** Unsets flag CWR + * @return Previous state of the flag */ +bool TCPHeader::unsetCWR(){ + u8 prev = h.th_flags & TH_CWR; + h.th_flags ^= TH_CWR; + return prev; +} /* End of unsetCWR() */ + + +/** Get CWR flag */ +bool TCPHeader::getCWR() const { + return h.th_flags & TH_CWR; +} /* End of getCWR() */ + + +/** Sets flag ECE/ECN + * @return Previous state of the flag */ +bool TCPHeader::setECE(){ + u8 prev = h.th_flags & TH_ECN; + h.th_flags |= TH_ECN; + return prev; +} /* End of setECE() */ + + +/** Unsets flag ECE/ECN + * @return Previous state of the flag */ +bool TCPHeader::unsetECE(){ + u8 prev = h.th_flags & TH_ECN; + h.th_flags ^= TH_ECN; + return prev; +} /* End of unsetECE() */ + + +/** Get CWR flag */ +bool TCPHeader::getECE() const { + return h.th_flags & TH_ECN; +} /* End of getECE() */ + + +/** Same as setECE() but with a different name since there are two possible + * ways to call this flag + * @return Previous state of the flag */ +bool TCPHeader::setECN(){ + u8 prev = h.th_flags & TH_ECN; + h.th_flags |= TH_ECN; + return prev; +} /* End of setECN() */ + + +/** Unsets flag ECE/ECN + * @return Previous state of the flag */ +bool TCPHeader::unsetECN(){ + u8 prev = h.th_flags & TH_ECN; + h.th_flags ^= TH_ECN; + return prev; +} /* End of unsetECN() */ + + +/** Get ECN flag */ +bool TCPHeader::getECN() const { + return h.th_flags & TH_ECN; +} /* End of getECN() */ + + +/** Sets flag URG + * @return Previous state of the flag */ +bool TCPHeader::setURG(){ + u8 prev = h.th_flags & TH_URG; + h.th_flags |= TH_URG; + return prev; +} /* End of setURG() */ + + +/** Unsets flag URG + * @return Previous state of the flag */ +bool TCPHeader::unsetURG(){ + u8 prev = h.th_flags & TH_URG; + h.th_flags ^= TH_URG; + return prev; +} /* End of unsetURG() */ + + +/** Get URG flag */ +bool TCPHeader::getURG() const { + return h.th_flags & TH_URG; +} /* End of getURG() */ + + +/** Sets flag ACK + * @return Previous state of the flag */ +bool TCPHeader::setACK(){ + u8 prev = h.th_flags & TH_ACK; + h.th_flags |= TH_ACK; + return prev; +} /* End of setACK() */ + + +/** Unsets flag ACK + * @return Previous state of the flag */ +bool TCPHeader::unsetACK(){ + u8 prev = h.th_flags & TH_ACK; + h.th_flags ^= TH_ACK; + return prev; +} /* End of unsetACK() */ + + +/** Get ACK flag */ +bool TCPHeader::getACK() const { + return h.th_flags & TH_ACK; +} /* End of getACK() */ + + +/** Sets flag PSH + * @return Previous state of the flag */ +bool TCPHeader::setPSH(){ + u8 prev = h.th_flags & TH_PSH; + h.th_flags |= TH_PSH; + return prev; +} /* End of setPSH() */ + + +/** Unsets flag PSH + * @return Previous state of the flag */ +bool TCPHeader::unsetPSH(){ + u8 prev = h.th_flags & TH_PSH; + h.th_flags ^= TH_PSH; + return prev; +} /* End of unsetPSH() */ + + +/** Get PSH flag */ +bool TCPHeader::getPSH() const { + return h.th_flags & TH_PSH; +} /* End of getPSH() */ + + +/** Sets flag RST + * @return Previous state of the flag */ +bool TCPHeader::setRST(){ + u8 prev = h.th_flags & TH_RST; + h.th_flags |= TH_RST; + return prev; +} /* End of setRST() */ + + +/** Unsets flag RST + * @return Previous state of the flag */ +bool TCPHeader::unsetRST(){ + u8 prev = h.th_flags & TH_RST; + h.th_flags ^= TH_RST; + return prev; +} /* End of unsetRST() */ + + +/** Get RST flag */ +bool TCPHeader::getRST() const { + return h.th_flags & TH_RST; +} /* End of getRST() */ + + +/** Sets flag SYN + * @return Previous state of the flag */ +bool TCPHeader::setSYN(){ + u8 prev = h.th_flags & TH_SYN; + h.th_flags |= TH_SYN; + return prev; +} /* End of setSYN() */ + + +/** Unsets flag SYN + * @return Previous state of the flag */ +bool TCPHeader::unsetSYN(){ + u8 prev = h.th_flags & TH_SYN; + h.th_flags ^= TH_SYN; + return prev; +} /* End of unsetSYN() */ + + +/** Get SYN flag */ +bool TCPHeader::getSYN() const { + return h.th_flags & TH_SYN; +} /* End of getSYN() */ + + +/** Sets flag FIN + * @return Previous state of the flag */ +bool TCPHeader::setFIN(){ + u8 prev = h.th_flags & TH_FIN; + h.th_flags |= TH_FIN; + return prev; +} /* End of setFIN() */ + + +/** Unsets flag FIN + * @return Previous state of the flag */ +bool TCPHeader::unsetFIN(){ + u8 prev = h.th_flags & TH_FIN; + h.th_flags ^= TH_FIN; + return prev; +} /* End of unsetFIN() */ + + +/** Get FIN flag */ +bool TCPHeader::getFIN() const { + return h.th_flags & TH_FIN; +} /* End of getFIN() */ + + +/** Sets window size. + * @warning Win number must be supplied in host byte order. This method + * performs byte order conversion using htons() */ +int TCPHeader::setWindow(u16 p){ + h.th_win = htons(p); + return OP_SUCCESS; +} /* End of setWindow() */ + + +/** Returns window size in HOST byte order. */ +u16 TCPHeader::getWindow() const { + return ntohs(h.th_win); +} /* End of getWindow() */ + + +/** Sets urgent pointer. + * @warning Pointer must be supplied in host byte order. This method + * performs byte order conversion using htons() */ +int TCPHeader::setUrgPointer(u16 l){ + h.th_urp = htons(l); + return OP_SUCCESS; +} /* End of setUrgPointer() */ + + +/** Returns Urgent Pointer in HOST byte order. */ +u16 TCPHeader::getUrgPointer() const { + return ntohs(h.th_urp); +} /* End of getUrgPointer() */ + + +int TCPHeader::setSum(struct in_addr src, struct in_addr dst){ + int bufflen; + u8 aux[ MAX_TCP_PAYLOAD_LEN ]; + /* FROM: RFC 1323: TCP Extensions for High Performance, March 4, 2009 + * + * "With IP Version 4, the largest amount of TCP data that can be sent in + * a single packet is 65495 bytes (64K - 1 - size of fixed IP and TCP + * headers)". + * + * In theory TCP should not worry about the practical max payload length + * because it is supposed to be independent of the network layer. However, + * since TCP does not have any length field and we need to allocate a + * buffer, we are using that value. (Note htat in UDPHeader.cc we do just + * the opposite, forget about the practical limitation and allow the + * theorical limit for the payload. */ + h.th_sum = 0; + + /* Copy packet contents to a buffer */ + bufflen=dumpToBinaryBuffer(aux, MAX_TCP_PAYLOAD_LEN); + + /* Compute checksum */ + h.th_sum = ipv4_pseudoheader_cksum(&src, &dst, IPPROTO_TCP, bufflen, (char *)aux); + + return OP_SUCCESS; +} /* End of setSum() */ + + +/** @warning Sum is set to supplied value with NO byte ordering conversion + * performed. */ +int TCPHeader::setSum(u16 s){ + h.th_sum = s; + return OP_SUCCESS; +} /* End of setSum() */ + + +int TCPHeader::setSum(){ + this->h.th_sum=0; + this->h.th_sum = this->compute_checksum(); + return OP_SUCCESS; +} /* End of setSum() */ + + +/** Set the TCP checksum field to a random value, which may accidentally + * match the correct checksum */ +int TCPHeader::setSumRandom(){ + h.th_sum=get_random_u16(); + return OP_SUCCESS; +} /* End of setSumRandom() */ + +/** Set the TCP checksum field to a random value. It takes the source and + * destination address to make sure the random generated sum does not + * accidentally match the correct checksum. This function only handles + * IPv4 address. */ +int TCPHeader::setSumRandom(struct in_addr source, struct in_addr destination){ + u16 correct_csum=0; + /* Compute the correct checksum */ + this->setSum(source, destination); + correct_csum=this->getSum(); + /* Generate numbers until one does not match the correct sum */ + while( (h.th_sum=get_random_u16())==correct_csum); + return OP_SUCCESS; +} /* End of setSumRandom() */ + + +/** Returns the TCP checksum field in NETWORK byte order */ +u16 TCPHeader::getSum() const { + return h.th_sum; +} /* End of getSum() */ + + +/* Copies the supplied buffer into the TCP options field. Note that the supplied + * buffer MUST NOT exceed MAX_TCP_OPTIONS_LEN octets and should be a multiple of + * four. If it is not a multiple of four, no error will be returned but the + * behaviour is unspecified. If this method is called passing NULL and zero + * ( t.setOptions(NULL, 0), any existing options are cleared, and the object's + * internal length is updated accordingly. Also, note that a call to setOptions() + * involves an automatic call to setOffset(), which updates the Offset field + * to take into account the new header length. If you need to set a bogus + * data offset, you can do so after calling setOptions(), but not before. + * It returns OP_SUCCESS on success and OP_FAILURE in case of error */ +int TCPHeader::setOptions(const u8 *optsbuff, size_t optslen){ + /* NULL and length=0 means delete existing options */ + if(optsbuff==NULL && optslen==0){ + this->tcpoptlen=0; + this->length=TCP_HEADER_LEN; + memset(this->h.options, 0, MAX_TCP_OPTIONS_LEN); + return OP_SUCCESS; + + /* Make sure params are safe to use */ + }else if(optsbuff==NULL || optslen==0 || optslen>MAX_TCP_OPTIONS_LEN){ + return OP_FAILURE; + + /* Copy supplied buffer into the options field, and update the offset field. */ + }else{ + memcpy(this->h.options, optsbuff, optslen); + this->tcpoptlen=optslen; + this->length=TCP_HEADER_LEN+optslen; + this->setOffset(); + return OP_SUCCESS; + } +} /* End of setOptions() */ + + +/* Returns a pointer to the start of the TCP options field. If the supplied + * "optslen" pointer is not NULL, the length of the options will be stored + * there. */ +const u8 *TCPHeader::getOptions(size_t *optslen) const { + if(optslen!=NULL) + *optslen=this->tcpoptlen; + return this->h.options; +} /* End of getOptions() */ + + +/* Returns the index-th option in the TCP header. On success it returns a + * structure filled with option information. If there is no index-th option, + * it returns a structure with st.value==NULL. Note that this function does + * not perform strict validity checking. It does check that the length claimed + * by the options does not exceed the available buffer but it does not check, + * for example, that the MSS option always contains a length of 4. Also, + * if the returned option type is TCPOPT_EOL or TCPOPT_NOOP, the len field + * would be set to zero and the "value" field should NOT be accessed, as it + * will not contain reliable information. */ +nping_tcp_opt_t TCPHeader::getOption(unsigned int index) const { + nping_tcp_opt_t *curr_opt=NULL; + u8 *curr_pnt=(u8 *)this->h.options; + int bytes_left=this->length - TCP_HEADER_LEN; + assert((this->length - TCP_HEADER_LEN) == this->tcpoptlen); + unsigned int optsfound=0; + nping_tcp_opt_t result; + memset(&result, 0, sizeof(nping_tcp_opt_t)); + + while(bytes_left>0){ + /* Use the opts structure as a template to access current option. It is + * OK to use it because we only access the first two elements. */ + curr_opt=(nping_tcp_opt_t *)curr_pnt; + + /* If we are right in the option that the caller wants, just return it */ + if(optsfound==index){ + result.type=curr_opt->type; + if(result.type==TCPOPT_EOL || result.type==TCPOPT_NOOP) + result.len=1; + else + result.len=curr_opt->len; + result.value=(u8 *)curr_pnt+2; + return result; + } + + /* Otherwise, we have to parse it, so we can skip it and access the next + * option */ + switch(curr_opt->type){ + + /* EOL or NOOP + +-+-+-+-+-+-+-+-+ + | X | + +-+-+-+-+-+-+-+-+ */ + case TCPOPT_EOL: + case TCPOPT_NOOP: + curr_pnt++; /* Skip one octet */ + bytes_left--; + break; + + /* TLV encoded option */ + default: + /* If we don't have as many octets as the option advertises, the + * option is bogus. Return failure. */ + if(bytes_leftlen) + return result; + curr_pnt+=curr_opt->len; + bytes_left-=curr_opt->len; + break; + } + optsfound++; + } + return result; +} + + +/* Returns a textual representation of a TCP Options code */ +const char *TCPHeader::optcode2str(u8 optcode){ + switch(optcode){ + case TCPOPT_EOL: + return "EOL"; + case TCPOPT_NOOP: + return "NOOP"; + case TCPOPT_MSS: + return "MSS"; + case TCPOPT_WSCALE: + return "WScale"; + case TCPOPT_SACKOK: + return "SAckOK"; + case TCPOPT_SACK: + return "SAck"; + case TCPOPT_ECHOREQ: + return "EchoReq"; + case TCPOPT_ECHOREP: + return "EchoRep"; + case TCPOPT_TSTAMP: + return "TStamp"; + case TCPOPT_POCP: + return "POCP"; + case TCPOPT_POSP: + return "POSP"; + case TCPOPT_CC: + return "CC"; + case TCPOPT_CCNEW: + return "CC.NEW"; + case TCPOPT_CCECHO: + return "CC.ECHO"; + case TCPOPT_ALTCSUMREQ: + return "AltSumReq"; + case TCPOPT_ALTCSUMDATA: + return "AltSumData"; + case TCPOPT_MD5: + return "MD5"; + case TCPOPT_SCPS: + return "SCPS"; + case TCPOPT_SNACK: + return "SNAck"; + case TCPOPT_QSRES: + return "QStart"; + case TCPOPT_UTO: + return "UTO"; + case TCPOPT_AO: + return "AO"; + default: + return "Unknown"; + } +} /* End of optcode2str() */ + + diff --git a/libnetutil/TCPHeader.h b/libnetutil/TCPHeader.h new file mode 100644 index 0000000000..0b3d6e0648 --- /dev/null +++ b/libnetutil/TCPHeader.h @@ -0,0 +1,290 @@ + +/*************************************************************************** + * TCPHeader.h -- The TCPHeader Class represents a TCP packet. It contains * + * methods to set the different header fields. These methods tipically * + * perform the necessary error checks and byte order conversions. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#ifndef __TCPHEADER_H__ +#define __TCPHEADER_H__ 1 + +#include "TransportLayerElement.h" + +/* TCP FLAGS */ +#define TH_FIN 0x01 +#define TH_SYN 0x02 +#define TH_RST 0x04 +#define TH_PSH 0x08 +#define TH_ACK 0x10 +#define TH_URG 0x20 +#define TH_ECN 0x40 +#define TH_CWR 0x80 + +/* TCP OPTIONS */ +#define TCPOPT_EOL 0 /* End of Option List (RFC793) */ +#define TCPOPT_NOOP 1 /* No-Operation (RFC793) */ +#define TCPOPT_MSS 2 /* Maximum Segment Size (RFC793) */ +#define TCPOPT_WSCALE 3 /* WSOPT - Window Scale (RFC1323) */ +#define TCPOPT_SACKOK 4 /* SACK Permitted (RFC2018) */ +#define TCPOPT_SACK 5 /* SACK (RFC2018) */ +#define TCPOPT_ECHOREQ 6 /* Echo (obsolete) (RFC1072)(RFC6247) */ +#define TCPOPT_ECHOREP 7 /* Echo Reply (obsolete) (RFC1072)(RFC6247) */ +#define TCPOPT_TSTAMP 8 /* TSOPT - Time Stamp Option (RFC1323) */ +#define TCPOPT_POCP 9 /* Partial Order Connection Permitted (obsol.) */ +#define TCPOPT_POSP 10 /* Partial Order Service Profile (obsolete) */ +#define TCPOPT_CC 11 /* CC (obsolete) (RFC1644)(RFC6247) */ +#define TCPOPT_CCNEW 12 /* CC.NEW (obsolete) (RFC1644)(RFC6247) */ +#define TCPOPT_CCECHO 13 /* CC.ECHO (obsolete) (RFC1644)(RFC6247) */ +#define TCPOPT_ALTCSUMREQ 14 /* TCP Alternate Checksum Request (obsolete) */ +#define TCPOPT_ALTCSUMDATA 15 /* TCP Alternate Checksum Data (obsolete) */ +#define TCPOPT_MD5 19 /* MD5 Signature Option (obsolete) (RFC2385) */ +#define TCPOPT_SCPS 20 /* SCPS Capabilities */ +#define TCPOPT_SNACK 21 /* Selective Negative Acknowledgements */ +#define TCPOPT_QSRES 27 /* Quick-Start Response (RFC4782) */ +#define TCPOPT_UTO 28 /* User Timeout Option (RFC5482) */ +#define TCPOPT_AO 29 /* TCP Authentication Option (RFC5925) */ + +/* Internal constants */ +#define TCP_HEADER_LEN 20 +#define MAX_TCP_OPTIONS_LEN 40 +#define MAX_TCP_PAYLOAD_LEN 65495 /**< Max len of a TCP packet */ + +/* Default header values */ +#define TCP_DEFAULT_SPORT 20 +#define TCP_DEFAULT_DPORT 80 +#define TCP_DEFAULT_SEQ 0 +#define TCP_DEFAULT_ACK 0 +#define TCP_DEFAULT_FLAGS 0x02 +#define TCP_DEFAULT_WIN 8192 +#define TCP_DEFAULT_URP 0 + + + +/* ++--------+--------+---------+--------... +| Type | Len | Value ++--------+--------+---------+--------... +*/ +struct nping_tcp_opt { + u8 type; /* Option type code. */ + u8 len; /* Option length. */ + u8 *value; /* Option value */ +}__attribute__((__packed__)); +typedef struct nping_tcp_opt nping_tcp_opt_t; + + +class TCPHeader : public TransportLayerElement { + + private: + /* + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Source Port | Destination Port | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Sequence Number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Acknowledgment Number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Offset| Res. |C|E|U|A|P|R|S|F| Window | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Checksum | Urgent Pointer | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Options | Padding | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + struct nping_tcp_hdr { + u16 th_sport; /* Source port */ + u16 th_dport; /* Destination port */ + u32 th_seq; /* Sequence number */ + u32 th_ack; /* Acknowledgement number */ + #if WORDS_BIGENDIAN + u8 th_off:4; /* Data offset */ + u8 th_x2:4; /* Reserved */ + #else + u8 th_x2:4; /* Reserved */ + u8 th_off:4; /* Data offset */ + #endif + u8 th_flags; /* Flags */ + u16 th_win; /* Window size */ + u16 th_sum; /* Checksum */ + u16 th_urp; /* Urgent pointer */ + + u8 options[MAX_TCP_OPTIONS_LEN ]; /* Space for TCP Options */ + }__attribute__((__packed__)); + + typedef struct nping_tcp_hdr nping_tcp_hdr_t; + + nping_tcp_hdr_t h; + + int tcpoptlen; /**< Length of TCP options */ + + void __tcppacketoptinfo(const u8 *optp, int len, char *result, int bufsize) const; + + public: + + TCPHeader(); + ~TCPHeader(); + void reset(); + u8 *getBufferPointer(); + int storeRecvData(const u8 *buf, size_t len); + int protocol_id() const; + int validate(); + int print(FILE *output, int detail) const; + + int setSourcePort(u16 p); + u16 getSourcePort() const; + + int setDestinationPort(u16 p); + u16 getDestinationPort() const; + + int setSeq(u32 p); + u32 getSeq() const; + + int setAck(u32 p); + u32 getAck() const; + + int setOffset(u8 o); + int setOffset(); + u8 getOffset() const; + + int setReserved(u8 r); + u8 getReserved() const; + + int setFlags(u8 f); + u8 getFlags() const; + u16 getFlags16() const; + bool setCWR(); + bool unsetCWR(); + bool getCWR() const; + bool setECE(); + bool unsetECE(); + bool getECE() const; + bool setECN(); + bool unsetECN(); + bool getECN() const; + bool setURG(); + bool unsetURG(); + bool getURG() const; + bool setACK(); + bool unsetACK(); + bool getACK() const; + bool setPSH(); + bool unsetPSH(); + bool getPSH() const; + bool setRST(); + bool unsetRST(); + bool getRST() const; + bool setSYN(); + bool unsetSYN(); + bool getSYN() const; + bool setFIN(); + bool unsetFIN(); + bool getFIN() const; + + int setWindow(u16 p); + u16 getWindow() const; + + int setUrgPointer(u16 l); + u16 getUrgPointer() const; + + int setSum(u16 s); + int setSum(struct in_addr source, struct in_addr destination); + int setSum(); + int setSumRandom(); + int setSumRandom(struct in_addr source, struct in_addr destination); + u16 getSum() const; + + int setOptions(const u8 *optsbuff, size_t optslen); + const u8 *getOptions(size_t *optslen) const; + nping_tcp_opt_t getOption(unsigned int index) const; + static const char *optcode2str(u8 optcode); + +}; /* End of class TCPHeader */ + +#endif /* __TCPHEADER_H__ */ diff --git a/libnetutil/TransportLayerElement.cc b/libnetutil/TransportLayerElement.cc new file mode 100644 index 0000000000..7b43a7f220 --- /dev/null +++ b/libnetutil/TransportLayerElement.cc @@ -0,0 +1,156 @@ +/*************************************************************************** + * TransportLayerElement.cc -- Class TransportLayerElement is a generic * + * class that represents a transport layer protocol header. Classes like * + * TCPHeader or UDPHeader inherit from it. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#include "TransportLayerElement.h" +#include "IPv4Header.h" +#include "IPv6Header.h" + + +/** Computes and returns the Internet checksum. + * @warning This method requires the object to be linked to either an IPv6Header + * object or an IPv4Header one, so the caller must ensure that objects are + * properly linked with calls to setNextElement() like this: + * + * IPv6Header ip6; + * TCPHeader tcp; + * [...] # Set header fields + * ip6.setNextElement(&tcp); + * tcp.setSum(); + * + * Note that there can be a number of other headers (like IPv6 extension headers) + * between the transport header and the network one, but all of them need to + * be linked in order for this method to traverse the list of headers and find + * the IP source and destination address, required to compute the checksum. So + * things like the following are OK: + * + * IPv6Header ip6; + * HopByHopHeader hop; + * RoutingHeader rte; + * FragmentHeader frg; + * UDPHeader udp; + * [...] # Set whatever header fields you need + * ip6.setNextElement(&hop); + * hop.setNextElement(&rte); + * rte.setNextElement(&frg); + * frg.setNextElement(&udp); + * udp.setSum(); # setSum() will be able to reach the IPv6Header. */ +u16 TransportLayerElement::compute_checksum(){ + PacketElement *hdr; + hdr=this->getPrevElement(); + u16 final_sum=0; + /* Traverse the list of headers backwards until we find an IP header */ + while(hdr!=NULL){ + if (hdr->protocol_id()==HEADER_TYPE_IPv6){ + IPv6Header *v6hdr=(IPv6Header *)hdr; + struct in6_addr i6src, i6dst; + memcpy(i6src.s6_addr, v6hdr->getSourceAddress(), 16); + memcpy(i6dst.s6_addr, v6hdr->getDestinationAddress(), 16); + u8 *buff=(u8 *)safe_malloc(this->getLen()); + this->dumpToBinaryBuffer(buff, this->getLen()); + final_sum=ipv6_pseudoheader_cksum(&i6src, &i6dst, this->protocol_id(), this->getLen(), buff); + free(buff); + return final_sum; + }else if(hdr->protocol_id()==HEADER_TYPE_IPv4){ + IPv4Header *v4hdr=(IPv4Header *)hdr; + struct in_addr i4src, i4dst; + memcpy(&(i4src.s_addr), v4hdr->getSourceAddress(), 4); + memcpy(&(i4dst.s_addr), v4hdr->getDestinationAddress(), 4); + u8 *buff=(u8 *)safe_malloc(this->getLen()); + this->dumpToBinaryBuffer(buff, this->getLen()); + final_sum=ipv4_pseudoheader_cksum(&i4src, &i4dst, this->protocol_id(), this->getLen(), buff); + free(buff); + return final_sum; + }else{ + hdr=hdr->getPrevElement(); + } + } + return 0; +} /* End of setSum() */ diff --git a/libnetutil/TransportLayerElement.h b/libnetutil/TransportLayerElement.h new file mode 100644 index 0000000000..ae36f5b0e2 --- /dev/null +++ b/libnetutil/TransportLayerElement.h @@ -0,0 +1,121 @@ +/*************************************************************************** + * TransportLayerElement.cc -- Class TransportLayerElement is a generic * + * class that represents a transport layer protocol header. Classes like * + * TCPHeader or UDPHeader inherit from it. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#ifndef TRANSPORTLAYERELEMENT_H +#define TRANSPORTLAYERELEMENT_H 1 + +#include "PacketElement.h" + +/// class TransportLayerElement - +class TransportLayerElement : public PacketElement { + + public: + + /* Returns source port. */ + virtual u16 getSourcePort() const = 0; + + /* Sets source port. */ + virtual int setSourcePort(u16 val) = 0; + + /* Returns destination port. */ + virtual u16 getDestinationPort() const = 0; + + /* Sets destination port. */ + virtual int setDestinationPort(u16 val) = 0; + + /* Sets checksum. */ + virtual int setSum(u16 val) = 0; + + protected: + u16 compute_checksum(); +}; + +#endif diff --git a/libnetutil/UDPHeader.cc b/libnetutil/UDPHeader.cc new file mode 100644 index 0000000000..64c3d7cb96 --- /dev/null +++ b/libnetutil/UDPHeader.cc @@ -0,0 +1,329 @@ + +/*************************************************************************** + * UDPHeader.cc -- The UDPHeader Class represents a UDP packet. It * + * contains methods to set the different header fields. These methods * + * tipically perform the necessary error checks and byte order * + * conversions. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#include "UDPHeader.h" + +/******************************************************************************/ +/* CONTRUCTORS, DESTRUCTORS AND INITIALIZATION METHODS */ +/******************************************************************************/ +UDPHeader::UDPHeader(){ + this->reset(); +} /* End of UDPHeader constructor */ + + +UDPHeader::~UDPHeader(){ + +} /* End of UDPHeader destructor */ + + +/** Sets every attribute to its default value */ +void UDPHeader::reset(){ + this->length=UDP_HEADER_LEN; + this->setSourcePort(UDP_DEFAULT_SPORT); + this->setDestinationPort(UDP_DEFAULT_DPORT); + this->setTotalLength(UDP_HEADER_LEN); + this->setSum(0); +} /* End of reset() */ + + +/******************************************************************************/ +/* PacketElement:: OVERWRITTEN METHODS */ +/******************************************************************************/ + +/** @warning This method is essential for the superclass getBinaryBuffer() + * method to work. Do NOT change a thing unless you know what you're doing */ +u8 * UDPHeader::getBufferPointer(){ + return (u8*)(&h); +} /* End of getBufferPointer() */ + + +/** Stores supplied packet in the internal buffer so the information + * can be accessed using the standard get & set methods. + * @warning The UDPHeader class is able to hold a maximum of 8 bytes. If the + * supplied buffer is longer than that, only the first 8 bytes will be stored + * in the internal buffer. + * @warning Supplied len MUST be at least 8 bytes (UDP header length). + * @return OP_SUCCESS on success and OP_FAILURE in case of error */ +int UDPHeader::storeRecvData(const u8 *buf, size_t len){ + if(buf==NULL || lenreset(); /* Re-init the object, just in case the caller had used it already */ + this->length=UDP_HEADER_LEN; + memcpy(&(this->h), buf, UDP_HEADER_LEN); + } + return OP_SUCCESS; +} /* End of storeRecvData() */ + + +/* Returns a protocol identifier. This is used by packet parsing funtions + * that return linked lists of PacketElement objects, to determine the protocol + * the object represents. */ +int UDPHeader::protocol_id() const { + return HEADER_TYPE_UDP; +} /* End of protocol_id() */ + + +/** Determines if the data stored in the object after an storeRecvData() call + * is valid and safe to use. This mainly checks the length of the data but may + * also test the value of certain protocol fields to ensure their correctness. + * @return the length, in bytes, of the header, if its found to be valid or + * OP_FAILURE (-1) otherwise. */ +int UDPHeader::validate(){ + if( this->length!=UDP_HEADER_LEN) + return OP_FAILURE; + else + return UDP_HEADER_LEN; +} /* End of validate() */ + + +/** Prints the contents of the header and calls print() on the next protocol + * header in the chain (if there is any). + * @return OP_SUCCESS on success and OP_FAILURE in case of error. */ +int UDPHeader::print(FILE *output, int detail) const { + fprintf(output, "UDP["); + fprintf(output, "%d", this->getSourcePort()); + fprintf(output, " >"); + fprintf(output, " %d", this->getDestinationPort()); + if(detail>=PRINT_DETAIL_HIGH) + fprintf(output, " len=%d", (int)this->getTotalLength() ); + if(detail>=PRINT_DETAIL_MED) + fprintf(output, " csum=0x%04X", ntohs( this->getSum() )); + fprintf(output, "]"); + if(this->next!=NULL){ + print_separator(output, detail); + next->print(output, detail); + } + return OP_SUCCESS; +} /* End of print() */ + + +/******************************************************************************/ +/* PROTOCOL-SPECIFIC METHODS */ +/******************************************************************************/ + +/** Sets source port. + * @warning Port must be supplied in host byte order. This method performs + * byte order conversion using htons() */ +int UDPHeader::setSourcePort(u16 p){ + h.uh_sport = htons(p); + return OP_SUCCESS; +} /* End of setSrcPort() */ + + +/** Returns source port in HOST byte order */ +u16 UDPHeader::getSourcePort() const { + return ntohs(h.uh_sport); +} /* End of getSrcPort() */ + + +/** Sets destination port. + * @warning Port must be supplied in host byte order. This method performs + * byte order conversion using htons() */ +int UDPHeader::setDestinationPort(u16 p){ + h.uh_dport = htons(p); + return OP_SUCCESS; +} /* End of setDstPort() */ + + +/** Returns destination port in HOST byte order */ +u16 UDPHeader::getDestinationPort() const { + return ntohs(h.uh_dport); +} /* End of getDstPort() */ + + +int UDPHeader::setSum(struct in_addr src, struct in_addr dst){ + int bufflen; + u8 aux[ 65535-8 ]; + /* FROM: RFC 5405 Unicast UDP Usage Guidelines, November 2008 + * "A UDP datagram is carried in a single IP packet and is hence limited to + * a maximum payload of 65,507 bytes for IPv4 and 65,527 bytes for IPv6" + * + * So, UDP is supposed to be able to carry 65535-8 bytes but in fact it can + * only carry 65,507 or 65,527. However, we are not taking that into account + * here because UDP is supposed to be independent of IPv4, IPv6 or + * whatever other network layer protocol is used to carry the UDP datagrams.*/ + h.uh_sum = 0; + + /* Copy packet contents to a buffer */ + bufflen=dumpToBinaryBuffer(aux, 65536-8 ); + + /* Compute checksum */ + h.uh_sum = ipv4_pseudoheader_cksum(&src, &dst, IPPROTO_UDP,bufflen, (char *) aux); + + return OP_SUCCESS; +} /* End of setSum() */ + + +/** @warning Sum is set to supplied value with NO byte ordering conversion + * performed. */ +int UDPHeader::setSum(u16 s){ + h.uh_sum = s; + return OP_SUCCESS; +} /* End of setSum() */ + + +int UDPHeader::setSum(){ + this->h.uh_sum=0; + this->h.uh_sum = this->compute_checksum(); + return OP_SUCCESS; +} /* End of setSum() */ + + +/** Set the UDP checksum field to a random value, which may accidentally + * match the correct checksum */ +int UDPHeader::setSumRandom(){ + h.uh_sum=(1 + (get_random_u16()%(65535-1))); /* Discard value zero */ + return OP_SUCCESS; +} /* End of setSumRandom() */ + + +/** Set the UDP checksum field to a random value. It takes the source and + * destination address to make sure the random generated sum does not + * accidentally match the correct checksum. This function only handles + * IPv4 address. */ +int UDPHeader::setSumRandom(struct in_addr source, struct in_addr destination){ + u16 correct_csum=0; + /* Compute the correct checksum */ + this->setSum(source, destination); + correct_csum=this->getSum(); + /* Generate numbers until one does not match the correct sum */ + while( (h.uh_sum=(1 + (get_random_u16()%(65535-1))))==correct_csum); + return OP_SUCCESS; +} /* End of setSumRandom() */ + + +u16 UDPHeader::getSum() const { + return h.uh_sum; +} /* End of getSum() */ + + +int UDPHeader::setTotalLength(){ + int mylen = 8; + int otherslen=0; + + if (next!=NULL) + otherslen=next->getLen(); + + /* FROM: RFC 5405 Unicast UDP Usage Guidelines, November 2008 + * "A UDP datagram is carried in a single IP packet and is hence limited to + * a maximum payload of 65,507 bytes for IPv4 and 65,527 bytes for IPv6" + * + * So, UDP is supposed to be able to carry 65535-8 bytes but in fact it can + * only carry 65,507 or 65,527. However, we are not taking that into account + * here because UDP is supposed to be independent of IPv4, IPv6 or + * whatever other network layer protocol is used to carry the UDP datagrams.*/ + if ((mylen+otherslen) > 65535 || (mylen+otherslen)<8 ){ + printf("UDPHeader::setTotalLenght(): Invalid length.\n"); + return OP_FAILURE; + } + + h.uh_ulen=htons( mylen+otherslen ); + + return OP_SUCCESS; +} /* End of setTotalLenght() */ + + +/** @warning Supplied value MUST be in HOST byte order */ +int UDPHeader::setTotalLength(u16 l){ + this->h.uh_ulen=htons(l); + return OP_SUCCESS; +} /* End of setTotalLenght() */ + + +/** @warning Returned value is in HOST byte order */ +u16 UDPHeader::getTotalLength() const { + return ntohs(this->h.uh_ulen); +} /* End of getTotalLenght() */ + + diff --git a/libnetutil/UDPHeader.h b/libnetutil/UDPHeader.h new file mode 100644 index 0000000000..fc92de11e2 --- /dev/null +++ b/libnetutil/UDPHeader.h @@ -0,0 +1,158 @@ + +/*************************************************************************** + * UDPHeader.h -- The UDPHeader Class represents a UDP packet. It contains * + * methods to set the different header fields. These methods tipically * + * perform the necessary error checks and byte order conversions. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ +/* This code was originally part of the Nping tool. */ + +#ifndef UDPHEADER_H +#define UDPHEADER_H 1 + +#include "TransportLayerElement.h" + +#define UDP_HEADER_LEN 8 + +/* Default header values */ +#define UDP_DEFAULT_SPORT 53 +#define UDP_DEFAULT_DPORT 53 + +class UDPHeader : public TransportLayerElement { + + private: + /* + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Source Port | Destination Port | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Length | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + struct nping_udp_hdr{ + u16 uh_sport; + u16 uh_dport; + u16 uh_ulen; + u16 uh_sum; + }__attribute__((__packed__)); + + typedef struct nping_udp_hdr nping_udp_hdr_t; + + nping_udp_hdr_t h; + + public: + + UDPHeader(); + ~UDPHeader(); + void reset(); + u8 *getBufferPointer(); + int storeRecvData(const u8 *buf, size_t len); + int protocol_id() const; + int validate(); + int print(FILE *output, int detail) const; + + int setSourcePort(u16 p); + u16 getSourcePort() const; + + int setDestinationPort(u16 p); + u16 getDestinationPort() const; + + int setTotalLength(); + int setTotalLength(u16 l); + u16 getTotalLength() const; + + int setSum(struct in_addr source, struct in_addr destination); + int setSum(u16 s); + int setSum(); + int setSumRandom(); + int setSumRandom(struct in_addr source, struct in_addr destination); + u16 getSum() const; + +}; /* End of class UDPHeader */ + + +#endif diff --git a/libnetutil/libnetutil.vcxproj b/libnetutil/libnetutil.vcxproj index c5bab213fe..6b9e9551a3 100644 --- a/libnetutil/libnetutil.vcxproj +++ b/libnetutil/libnetutil.vcxproj @@ -74,10 +74,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libnetutil/netutil.cc b/libnetutil/netutil.cc index 9a6c77368d..ed648e5084 100644 --- a/libnetutil/netutil.cc +++ b/libnetutil/netutil.cc @@ -1677,14 +1677,18 @@ int islocalhost(const struct sockaddr_storage *const ss) { /* Determines whether the supplied address corresponds to a private, * non-Internet-routable address. See RFC1918 for details. * Returns 1 if the address is private or 0 otherwise. */ -int isipprivate(const struct in_addr *const addr) { +int isipprivate(const struct sockaddr_storage *addr) { + const struct sockaddr_in *sin; char *ipc; unsigned char i1, i2; if (!addr) return 0; + if (addr->ss_family != AF_INET) + return 0; + sin = (struct sockaddr_in *) addr; - ipc = (char *) &(addr->s_addr); + ipc = (char *) &(sin->sin_addr.s_addr); i1 = ipc[0]; i2 = ipc[1]; diff --git a/libnetutil/netutil.h b/libnetutil/netutil.h index c1b32e48af..6c23d98da3 100644 --- a/libnetutil/netutil.h +++ b/libnetutil/netutil.h @@ -106,6 +106,10 @@ extern "C" { #include "dnet.h" + +/* It is VERY important to never change the value of these two constants. + * Specially, OP_FAILURE should never be positive, as some pieces of code take + * that for granted. */ enum { OP_FAILURE = -1, OP_SUCCESS = 0 }; @@ -383,7 +387,7 @@ int islocalhost(const struct sockaddr_storage *const ss); /* Determines whether the supplied address corresponds to a private, * non-Internet-routable address. See RFC1918 for details. * Returns 1 if the address is private or 0 otherwise. */ -int isipprivate(const struct in_addr *const addr); +int isipprivate(const struct sockaddr_storage *addr); /* Takes binary data found in the IP Options field of an IPv4 packet * and returns a string containing an ASCII description of the options diff --git a/libnetutil/npacket.cc b/libnetutil/npacket.cc new file mode 100644 index 0000000000..4dbe46ce76 --- /dev/null +++ b/libnetutil/npacket.cc @@ -0,0 +1,119 @@ + +/*************************************************************************** + * netutil.h -- The main include file exposing the external API for * + * libnetutil, a library that provides network-related functions or * + * classes that make it easier to handle things like network interfaces, * + * routing tables, raw packet manipulation, etc. The lib was originally * + * written for use in the Nmap Security Scanner ( http://nmap.org ). * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ + +#include +#include +#include +#include + +/* Uncomment the following lines to enable debugging output */ +//#ifndef NPACKET_DEBUG +//#define NPACKET_DEBUG 1 +//#endif + +/* Print debug messages to stdout and then return. A newline + * character is printed automatically after the supplied text.*/ +void npacket_debug(const char *str, ...){ +#ifdef NPACKET_DEBUG + va_list list; + char errstr[1025]; + memset(errstr,0, 1024); + va_start(list, str); + fflush(stdout); + vfprintf(stdout, str, list); + fprintf(stdout,"\n"); + va_end(list); +#endif +} /* End of npacket_debug() */ + + diff --git a/libnetutil/npacket.h b/libnetutil/npacket.h new file mode 100644 index 0000000000..3dcea27445 --- /dev/null +++ b/libnetutil/npacket.h @@ -0,0 +1,128 @@ + +/*************************************************************************** + * netutil.h -- The main include file exposing the external API for * + * libnetutil, a library that provides network-related functions or * + * classes that make it easier to handle things like network interfaces, * + * routing tables, raw packet manipulation, etc. The lib was originally * + * written for use in the Nmap Security Scanner ( http://nmap.org ). * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * * + * The Nmap Security Scanner is (C) 1996-2011 Insecure.Com LLC. Nmap is * + * also a registered trademark of Insecure.Com LLC. This program is free * + * software; you may redistribute and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation; Version 2 with the clarifications and exceptions described * + * below. This guarantees your right to use, modify, and redistribute * + * this software under certain conditions. If you wish to embed Nmap * + * technology into proprietary software, we sell alternative licenses * + * (contact sales@insecure.com). Dozens of software vendors already * + * license Nmap technology such as host discovery, port scanning, OS * + * detection, and version detection. * + * * + * Note that the GPL places important restrictions on "derived works", yet * + * it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we consider an application to constitute a * + * "derivative work" for the purpose of this license if it does any of the * + * following: * + * o Integrates source code from Nmap * + * o Reads or includes Nmap copyrighted data files, such as * + * nmap-os-db or nmap-service-probes. * + * o Executes Nmap and parses the results (as opposed to typical shell or * + * execution-menu apps, which simply display raw Nmap output and so are * + * not derivative works.) * + * o Integrates/includes/aggregates Nmap into a proprietary executable * + * installer, such as those produced by InstallShield. * + * o Links to a library or executes a program that does any of the above * + * * + * The term "Nmap" should be taken to also include any portions or derived * + * works of Nmap. This list is not exclusive, but is meant to clarify our * + * interpretation of derived works with some common examples. Our * + * interpretation applies only to Nmap--we don't speak for other people's * + * GPL works. * + * * + * If you have any questions about the GPL licensing restrictions on using * + * Nmap in non-GPL works, we would be happy to help. As mentioned above, * + * we also offer alternative license to integrate Nmap into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates as well as helping to * + * fund the continued development of Nmap technology. Please email * + * sales@insecure.com for further information. * + * * + * As a special exception to the GPL terms, Insecure.Com LLC grants * + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. You must obey the GNU GPL in all * + * respects for all of the code used other than OpenSSL. If you modify * + * this file, you may extend this exception to your version of the file, * + * but you are not obligated to do so. * + * * + * If you received these files with a written license agreement or * + * contract stating terms other than the terms above, then that * + * alternative license agreement takes precedence over these comments. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port Nmap to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to nmap-dev@insecure.org for possible incorporation into the main * + * distribution. By sending these changes to Fyodor or one of the * + * Insecure.Org development mailing lists, it is assumed that you are * + * offering the Nmap Project (Insecure.Com LLC) the unlimited, * + * non-exclusive right to reuse, modify, and relicense the code. Nmap * + * will always be available Open Source, but this is important because the * + * inability to relicense code has caused devastating problems for other * + * Free Software projects (such as KDE and NASM). We also occasionally * + * relicense the code to third parties as discussed above. If you wish to * + * specify special license conditions of your contributions, just say so * + * when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License v2.0 for more details at * + * http://www.gnu.org/licenses/gpl-2.0.html , or in the COPYING file * + * included with Nmap. * + * * + ***************************************************************************/ + +/* $Id: npacket.h 18098 2010-06-14 11:50:12Z luis $ */ + +#ifndef __NPACKET_H__ +#define __NPACKET_H__ 1 + + +#include "ApplicationLayerElement.h" +#include "ARPHeader.h" +#include "DataLinkLayerElement.h" +#include "EthernetHeader.h" +#include "ICMPHeader.h" +#include "ICMPv4Header.h" +#include "ICMPv6Header.h" +#include "ICMPv6Option.h" +#include "ICMPv6RRBody.h" +#include "IPv4Header.h" +#include "IPv6Header.h" +#include "NetworkLayerElement.h" +#include "PacketElement.h" +#include "RawData.h" +#include "TCPHeader.h" +#include "TransportLayerElement.h" +#include "UDPHeader.h" +#include "HopByHopHeader.h" +#include "DestOptsHeader.h" +#include "FragmentHeader.h" +#include "RoutingHeader.h" +#include "PacketParser.h" + +void npacket_debug(const char *str, ...) + __attribute__ ((noreturn)) + __attribute__ ((format (printf, 1, 2))); + +#endif /* __NPACKET_H__ */ + diff --git a/libpcre/config.h.in b/libpcre/config.h.in index a7fe1f48a9..8a0d4710ec 100644 --- a/libpcre/config.h.in +++ b/libpcre/config.h.in @@ -175,6 +175,9 @@ them both to 0; an emulation function will be used. */ /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME +/* Define to the home page for this package. */ +#undef PACKAGE_URL + /* Define to the version of this package. */ #undef PACKAGE_VERSION diff --git a/mswin32/nmap.sln b/mswin32/nmap.sln index b6276437e6..ea93b1e52c 100644 --- a/mswin32/nmap.sln +++ b/mswin32/nmap.sln @@ -1,8 +1,9 @@ Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 +# Visual C++ Express 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nmap", "nmap.vcxproj", "{361719F0-AB42-4C93-9DE8-7D2144B96625}" ProjectSection(ProjectDependencies) = postProject {99157C3F-39F6-4663-99D7-1D9C1484494E} = {99157C3F-39F6-4663-99D7-1D9C1484494E} + {A7BE3D76-F20C-40C5-8986-DE4028B3B57D} = {A7BE3D76-F20C-40C5-8986-DE4028B3B57D} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nsock", "..\nsock\nsock.vcxproj", "{F8D6D1E3-D4EA-402C-98AA-168E5309BAF4}" @@ -21,6 +22,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nping", "..\nping\nping.vcx EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libnetutil", "..\libnetutil\libnetutil.vcxproj", "{99157C3F-39F6-4663-99D7-1D9C1484494E}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblinear", "..\liblinear\liblinear.vcxproj", "{A7BE3D76-F20C-40C5-8986-DE4028B3B57D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -76,6 +79,12 @@ Global {99157C3F-39F6-4663-99D7-1D9C1484494E}.Ncat Static|Win32.ActiveCfg = Release|Win32 {99157C3F-39F6-4663-99D7-1D9C1484494E}.Release|Win32.ActiveCfg = Release|Win32 {99157C3F-39F6-4663-99D7-1D9C1484494E}.Release|Win32.Build.0 = Release|Win32 + {A7BE3D76-F20C-40C5-8986-DE4028B3B57D}.Debug|Win32.ActiveCfg = Debug|Win32 + {A7BE3D76-F20C-40C5-8986-DE4028B3B57D}.Debug|Win32.Build.0 = Debug|Win32 + {A7BE3D76-F20C-40C5-8986-DE4028B3B57D}.Ncat Static|Win32.ActiveCfg = Release|Win32 + {A7BE3D76-F20C-40C5-8986-DE4028B3B57D}.Ncat Static|Win32.Build.0 = Release|Win32 + {A7BE3D76-F20C-40C5-8986-DE4028B3B57D}.Release|Win32.ActiveCfg = Release|Win32 + {A7BE3D76-F20C-40C5-8986-DE4028B3B57D}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/mswin32/nmap.vcxproj b/mswin32/nmap.vcxproj index bf4a6b644e..33910a9689 100644 --- a/mswin32/nmap.vcxproj +++ b/mswin32/nmap.vcxproj @@ -54,7 +54,7 @@ Disabled - ..\liblua;.;..;../nbase;../libpcre;winip;..\nsock\include;pcap-include;..\libdnet-stripped\include;OpenSSL\include;%(AdditionalIncludeDirectories) + ..\liblua;.;..;../nbase;../libpcre;winip;..\nsock\include;pcap-include;..\libdnet-stripped\include;OpenSSL\include;..\liblinear;%(AdditionalIncludeDirectories) WIN32;_CONSOLE;%(PreprocessorDefinitions) false false @@ -73,10 +73,10 @@ CompileAsCpp - liblua.lib;nsock.lib;libpcre.lib;nbase.lib;libdnet-stripped.lib;ws2_32.lib;IPHlpAPI.Lib;wpcap.lib;packet.lib;advapi32.lib;libeay32.lib;ssleay32.lib;shell32.lib;libnetutil.lib + liblua.lib;nsock.lib;libpcre.lib;nbase.lib;libdnet-stripped.lib;liblinear.lib;ws2_32.lib;IPHlpAPI.Lib;wpcap.lib;packet.lib;advapi32.lib;libeay32.lib;ssleay32.lib;shell32.lib;libnetutil.lib .\Debug\nmap.exe true - lib;..\liblua;..\libpcre;..\nsock;..\nbase;..\libdnet-stripped;../libnetutil;OpenSSL\lib;%(AdditionalLibraryDirectories) + lib;..\liblua;..\libpcre;..\nsock;..\nbase;..\libdnet-stripped;../libnetutil;OpenSSL\lib;..\liblinear;%(AdditionalLibraryDirectories) %(IgnoreSpecificDefaultLibraries) packet.dll;wpcap.dll;iphlpapi.dll;%(DelayLoadDLLs) true @@ -100,7 +100,7 @@ MaxSpeed OnlyExplicitInline - .;..;../liblua;../nbase;../libpcre;winip;..\nsock\include;pcap-include;..\libdnet-stripped\include;OpenSSL\include;%(AdditionalIncludeDirectories) + .;..;../liblua;../nbase;../libpcre;winip;..\nsock\include;pcap-include;..\libdnet-stripped\include;OpenSSL\include;..\liblinear;%(AdditionalIncludeDirectories) WIN32;_CONSOLE;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -115,10 +115,10 @@ CompileAsCpp - liblua.lib;nsock.lib;libpcre.lib;nbase.lib;libdnet-stripped.lib;ws2_32.lib;IPHlpAPI.Lib;wpcap.lib;packet.lib;advapi32.lib;libeay32.lib;ssleay32.lib;shell32.lib;libnetutil.lib + liblua.lib;nsock.lib;libpcre.lib;nbase.lib;libdnet-stripped.lib;liblinear.lib;ws2_32.lib;IPHlpAPI.Lib;wpcap.lib;packet.lib;advapi32.lib;libeay32.lib;ssleay32.lib;shell32.lib;libnetutil.lib .\Release/nmap.exe true - lib;..\liblua;..\libpcre;..\nsock;..\nbase;..\libdnet-stripped;../libnetutil;OpenSSL\lib;%(AdditionalLibraryDirectories) + lib;..\liblua;..\libpcre;..\nsock;..\nbase;..\libdnet-stripped;../libnetutil;OpenSSL\lib;..\liblinear;%(AdditionalLibraryDirectories) %(IgnoreSpecificDefaultLibraries) packet.dll;wpcap.dll;iphlpapi.dll;%(DelayLoadDLLs) .\Release/nmap.pdb @@ -134,6 +134,8 @@ + + @@ -185,6 +187,7 @@ + diff --git a/nmap.cc b/nmap.cc index f0dfe5bacb..6c78112465 100644 --- a/nmap.cc +++ b/nmap.cc @@ -940,8 +940,7 @@ void parse_options(int argc, char **argv) { o.script = 1; #endif if (o.isr00t) { - if (o.af() == AF_INET) - o.osscan++; + o.osscan++; o.traceroute = true; } break; @@ -1306,8 +1305,10 @@ void apply_delayed_options() { if (delayed_options.pre_host_timeout != -1) o.host_timeout = delayed_options.pre_host_timeout; - if (o.osscan) + if (o.osscan) { o.reference_FPs = parse_fingerprint_reference_file("nmap-os-db"); + o.os_labels_ipv6 = load_fp_matches(); + } validate_scan_lists(ports,o); o.ValidateOptions(); @@ -1945,8 +1946,10 @@ int nmap_main(int argc, char *argv[]) { } } - if (o.osscan) - os_scan2(Targets); + if (o.osscan){ + OSScan os_engine; + os_engine.os_scan(Targets); + } if (o.traceroute) traceroute(Targets); diff --git a/nmap.h b/nmap.h index a53257ef4c..2a86edc78b 100644 --- a/nmap.h +++ b/nmap.h @@ -252,8 +252,8 @@ void *realloc(); #ifndef NMAP_VERSION /* Edit this definition only within the quotes, because it is read from this file by the makefiles. */ -#define NMAP_VERSION "5.59BETA3" -#define NMAP_NUM_VERSION "5.59.0.3" +#define NMAP_VERSION "5.59BETA1" +#define NMAP_NUM_VERSION "5.59.0.1" #endif /* User configurable #defines: */ diff --git a/nse_nmaplib.cc b/nse_nmaplib.cc index 052263c15a..23baf1c168 100644 --- a/nse_nmaplib.cc +++ b/nse_nmaplib.cc @@ -184,7 +184,7 @@ void set_hostinfo(lua_State *L, Target *currenths) { lua_newtable(L); // this will run at least one time and at most 8 times, see if condition for(i = 0; FPR->accuracy[i] == 1; i++) { - lua_pushstring(L, FPR->prints[i]->OS_name); + lua_pushstring(L, FPR->matches[i]->OS_name); lua_rawseti(L, -2, i+1); } lua_setfield(L, -2, "os"); diff --git a/osscan.cc b/osscan.cc index 0d499d43ba..a4c4c4a483 100644 --- a/osscan.cc +++ b/osscan.cc @@ -206,8 +206,6 @@ FingerPrintDB::~FingerPrintDB() { } FingerPrint::FingerPrint() { - line = 0; - OS_name = NULL; } const struct AVal *FingerTest::getattrbyname(const char *name) const { @@ -460,11 +458,11 @@ double compare_fingerprints(FingerPrint *referenceFP, FingerPrint *observedFP, /* Takes a fingerprint and looks for matches inside the passed in reference fingerprint DB. The results are stored in in FPR (which - must point to an instantiated FingerPrintResults class) -- results + must point to an instantiated FingerPrintResultsIPv4 class) -- results will be reverse-sorted by accuracy. No results below accuracy_threshhold will be included. The max matches returned is - the maximum that fits in a FingerPrintResults class. */ -void match_fingerprint(FingerPrint *FP, FingerPrintResults *FPR, + the maximum that fits in a FingerPrintResultsIPv4 class. */ +void match_fingerprint(FingerPrint *FP, FingerPrintResultsIPv4 *FPR, FingerPrintDB *DB, double accuracy_threshold) { double FPR_entrance_requirement = accuracy_threshold; /* accuracy must be at least this big @@ -474,10 +472,10 @@ void match_fingerprint(FingerPrint *FP, FingerPrintResults *FPR, double acc; int state; int skipfp; - int max_prints = sizeof(FPR->prints) / sizeof(FingerPrint *); + int max_prints = sizeof(FPR->matches) / sizeof(FPR->matches[0]); int idx; double tmp_acc=0.0, tmp_acc2; /* These are temp buffers for list swaps */ - FingerPrint *tmp_FP = NULL, *tmp_FP2; + FingerMatch *tmp_FP = NULL, *tmp_FP2; assert(FP); assert(FPR); @@ -495,12 +493,12 @@ void match_fingerprint(FingerPrint *FP, FingerPrintResults *FPR, state = 0; for (idx=0; idx < FPR->num_matches; idx++) { - if (strcmp(FPR->prints[idx]->OS_name, (*current_os)->OS_name) == 0) { + if (strcmp(FPR->matches[idx]->OS_name, (*current_os)->match.OS_name) == 0) { if (FPR->accuracy[idx] >= acc) { skipfp = 1; /* Skip it -- a higher version is already in list */ } else { /* We must shift the list left to delete this sucker */ - memmove(FPR->prints + idx, FPR->prints + idx + 1, + memmove(FPR->matches + idx, FPR->matches + idx + 1, (FPR->num_matches - 1 - idx) * sizeof(FingerPrint *)); memmove(FPR->accuracy + idx, FPR->accuracy + idx + 1, (FPR->num_matches - 1 - idx) * sizeof(double)); @@ -528,18 +526,18 @@ void match_fingerprint(FingerPrint *FP, FingerPrintResults *FPR, if (state == 1) { /* Push tmp_acc and tmp_FP onto the next idx */ tmp_acc2 = FPR->accuracy[idx+1]; - tmp_FP2 = FPR->prints[idx+1]; + tmp_FP2 = FPR->matches[idx+1]; FPR->accuracy[idx+1] = tmp_acc; - FPR->prints[idx+1] = tmp_FP; + FPR->matches[idx+1] = tmp_FP; tmp_acc = tmp_acc2; tmp_FP = tmp_FP2; } else if (FPR->accuracy[idx + 1] < acc) { /* OK, I insert the sucker into the next slot ... */ tmp_acc = FPR->accuracy[idx+1]; - tmp_FP = FPR->prints[idx+1]; - FPR->prints[idx+1] = *current_os; + tmp_FP = FPR->matches[idx+1]; + FPR->matches[idx+1] = &(*current_os)->match; FPR->accuracy[idx+1] = acc; state = 1; } @@ -595,8 +593,9 @@ static const char *dist_method_fp_string(enum dist_calc_method method) top of a fingerprint. Gives info which might be useful when the FPrint is submitted (eg Nmap version, etc). Result is written (up to ostrlen) to the ostr var passed in */ -static void WriteSInfo(char *ostr, int ostrlen, bool isGoodFP, - const struct in_addr * const addr, int distance, +void WriteSInfo(char *ostr, int ostrlen, bool isGoodFP, + const char *engine_id, + const struct sockaddr_storage *addr, int distance, enum dist_calc_method distance_calculation_method, const u8 *mac, int openTcpPort, int closedTcpPort, int closedUdpPort) { @@ -629,8 +628,8 @@ static void WriteSInfo(char *ostr, int ostrlen, bool isGoodFP, if (mac) Snprintf(macbuf, sizeof(macbuf), "%%M=%02X%02X%02X", mac[0], mac[1], mac[2]); - Snprintf(ostr, ostrlen, "SCAN(V=%s%%D=%d/%d%%OT=%s%%CT=%s%%CU=%s%%PV=%c%s%s%%G=%c%s%%TM=%X%%P=%s)", - NMAP_VERSION, ltime->tm_mon + 1, ltime->tm_mday, + Snprintf(ostr, ostrlen, "SCAN(V=%s%%E=%s%%D=%d/%d%%OT=%s%%CT=%s%%CU=%s%%PV=%c%s%s%%G=%c%s%%TM=%X%%P=%s)", + NMAP_VERSION, engine_id, ltime->tm_mon + 1, ltime->tm_mday, otbuf, ctbuf, cubuf, isipprivate(addr) ? 'Y' : 'N', dsbuf, dcbuf, isGoodFP ? 'Y' : 'N', macbuf, (int) timep, NMAP_PLATFORM); } @@ -804,7 +803,7 @@ static bool FingerTest_lessthan(const FingerTest* a, const FingerTest* b) { are included only once. If wrapit is true, the string is wrapped for submission. */ const char *mergeFPs(FingerPrint *FPs[], int numFPs, bool isGoodFP, - const struct in_addr * const addr, int distance, + const struct sockaddr_storage *addr, int distance, enum dist_calc_method distance_calculation_method, const u8 *mac, int openTcpPort, int closedTcpPort, int closedUdpPort, bool wrapit) { @@ -872,7 +871,7 @@ const char *mergeFPs(FingerPrint *FPs[], int numFPs, bool isGoodFP, p = str; /* Lets start by writing the fake "SCAN" test for submitting fingerprints */ - WriteSInfo(p, sizeof(str), isGoodFP, addr, distance, distance_calculation_method, mac, openTcpPort, closedTcpPort, closedUdpPort); + WriteSInfo(p, sizeof(str), isGoodFP, "4", addr, distance, distance_calculation_method, mac, openTcpPort, closedTcpPort, closedUdpPort); p = p + strlen(str); if (!wrapit) *p++ = '\n'; @@ -997,16 +996,16 @@ static void parse_classline(FingerPrint *FP, char *thisline, int lineno) { end = strchr(begin, '\0'); os_class.Device_Type = string_pool_substr_strip(begin, end); - FP->OS_class.push_back(os_class); + FP->match.OS_class.push_back(os_class); } static void parse_cpeline(FingerPrint *FP, char *thisline, int lineno) { const char *cpe; - if (FP->OS_class.empty()) + if (FP->match.OS_class.empty()) fatal("\"CPE\" line without preceding \"Class\" at line %d", lineno); - OS_Classification& osc = FP->OS_class.back(); + OS_Classification& osc = FP->match.OS_class.back(); if (thisline == NULL || strncmp(thisline, "CPE ", 4) != 0) fatal("Bogus line #%d (%s) passed to %s()", lineno, thisline, __func__); @@ -1050,7 +1049,7 @@ FingerPrint *parse_single_fingerprint(char *fprint_orig) { if (strncmp(thisline, "Fingerprint ", 12) == 0) { /* Ignore a second Fingerprint line if it appears. */ - if (FP->OS_name == NULL) { + if (FP->match.OS_name == NULL) { p = thisline + 12; while (*p && isspace((int) (unsigned char) *p)) p++; @@ -1061,9 +1060,9 @@ FingerPrint *parse_single_fingerprint(char *fprint_orig) { while (q > p && isspace((int) (unsigned char) *(--q))) ; - FP->OS_name = (char *) cp_alloc(q - p + 2); - memcpy(FP->OS_name, p, q - p + 1); - FP->OS_name[q - p + 1] = '\0'; + FP->match.OS_name = (char *) cp_alloc(q - p + 2); + memcpy(FP->match.OS_name, p, q - p + 1); + FP->match.OS_name[q - p + 1] = '\0'; } } else if (strncmp(thisline, "MatchPoints", 11) == 0) { p = thisline + 11; @@ -1150,7 +1149,7 @@ FingerPrintDB *parse_fingerprint_file(const char *fname) { current = new FingerPrint; if (parsingMatchPoints) { - current->OS_name = NULL; + current->match.OS_name = NULL; DB->MatchPoints = current; } else { DB->prints.push_back(current); @@ -1168,12 +1167,12 @@ FingerPrintDB *parse_fingerprint_file(const char *fname) { if (q < p) fatal("Parse error on line %d of fingerprint: %s", lineno, line); - current->OS_name = (char *) cp_alloc(q - p + 2); - memcpy(current->OS_name, p, q - p + 1); - current->OS_name[q - p + 1] = '\0'; + current->match.OS_name = (char *) cp_alloc(q - p + 2); + memcpy(current->match.OS_name, p, q - p + 1); + current->match.OS_name[q - p + 1] = '\0'; } - current->line = lineno; + current->match.line = lineno; /* Now we read the fingerprint itself */ while (fgets(line, sizeof(line), fp)) { diff --git a/osscan.h b/osscan.h index 4767597abd..ae3958a0bb 100644 --- a/osscan.h +++ b/osscan.h @@ -144,18 +144,24 @@ double compare_fingerprints(FingerPrint *referenceFP, FingerPrint *observedFP, /* Takes a fingerprint and looks for matches inside the passed in reference fingerprint DB. The results are stored in in FPR (which - must point to an instantiated FingerPrintResults class) -- results + must point to an instantiated FingerPrintResultsIPv4 class) -- results will be reverse-sorted by accuracy. No results below accuracy_threshhold will be included. The max matches returned is - the maximum that fits in a FingerPrintResults class. */ -void match_fingerprint(FingerPrint *FP, FingerPrintResults *FPR, + the maximum that fits in a FingerPrintResultsIPv4 class. */ +void match_fingerprint(FingerPrint *FP, FingerPrintResultsIPv4 *FPR, FingerPrintDB *DB, double accuracy_threshold); /* Returns true if perfect match -- if num_subtests & num_subtests_succeeded are non_null it updates them. if shortcircuit is zero, it does all the tests, otherwise it returns when the first one fails */ void freeFingerPrint(FingerPrint *FP); +void WriteSInfo(char *ostr, int ostrlen, bool isGoodFP, + const char *engine_id, + const struct sockaddr_storage *addr, int distance, + enum dist_calc_method distance_calculation_method, + const u8 *mac, int openTcpPort, + int closedTcpPort, int closedUdpPort); const char *mergeFPs(FingerPrint *FPs[], int numFPs, bool isGoodFP, - const struct in_addr * const addr, int distance, + const struct sockaddr_storage *addr, int distance, enum dist_calc_method distance_calculation_method, const u8 *mac, int openTcpPort, int closedTcpPort, int closedUdpPort, bool wrapit); diff --git a/osscan2.cc b/osscan2.cc index 5c29174446..190df77d0c 100644 --- a/osscan2.cc +++ b/osscan2.cc @@ -97,6 +97,7 @@ #include "NmapOps.h" #include "Target.h" #include "utils.h" +#include "FPEngine.h" #include #include @@ -755,8 +756,8 @@ static void endRound(OsScanInfo *OSI, HostOsScan *HOS, int roundNum) { HOS->makeFP(hsi->hss); hsi->FPs[roundNum] = hsi->hss->getFP(); - hsi->target->FPR->FPs[roundNum] = hsi->FPs[roundNum]; - hsi->target->FPR->numFPs = roundNum + 1; + hsi->FPR->FPs[roundNum] = hsi->FPs[roundNum]; + hsi->FPR->numFPs = roundNum + 1; double tr = hsi->hss->timingRatio(); hsi->target->FPR->maxTimingRatio = MAX(hsi->target->FPR->maxTimingRatio, tr); match_fingerprint(hsi->FPs[roundNum], &hsi->FP_matches[roundNum], @@ -768,7 +769,7 @@ static void endRound(OsScanInfo *OSI, HostOsScan *HOS, int roundNum) { if (roundNum > 0) { if(o.verbose) log_write(LOG_STDOUT, "WARNING: OS didn't match until try #%d\n", roundNum + 1); } - match_fingerprint(hsi->target->FPR->FPs[roundNum], hsi->target->FPR, + match_fingerprint(hsi->FPR->FPs[roundNum], hsi->FPR, o.reference_FPs, OSSCAN_GUESS_THRESHOLD); hsi->isCompleted = true; } @@ -810,7 +811,7 @@ static void findBestFPs(OsScanInfo *OSI) { /* Now lets find the best match */ bestacc = 0; bestaccidx = 0; - for(i=0; i < hsi->target->FPR->numFPs; i++) { + for(i=0; i < hsi->FPR->numFPs; i++) { if (hsi->FP_matches[i].overall_results == OSSCAN_SUCCESS && hsi->FP_matches[i].num_matches > 0 && hsi->FP_matches[i].accuracy[0] > bestacc) { @@ -824,7 +825,7 @@ static void findBestFPs(OsScanInfo *OSI) { // Now we redo the match, since target->FPR has various data (such as // target->FPR->numFPs) which is not in FP_matches[bestaccidx]. This is // kinda ugly. - match_fingerprint(hsi->target->FPR->FPs[bestaccidx], hsi->target->FPR, + match_fingerprint(hsi->FPR->FPs[bestaccidx], (FingerPrintResultsIPv4 *) hsi->target->FPR, o.reference_FPs, OSSCAN_GUESS_THRESHOLD); } } @@ -833,17 +834,17 @@ static void findBestFPs(OsScanInfo *OSI) { static void printFP(OsScanInfo *OSI) { list::iterator hostI; HostOsScanInfo *hsi = NULL; - FingerPrintResults *FPR; + FingerPrintResultsIPv4 *FPR; for(hostI = OSI->incompleteHosts.begin(); hostI != OSI->incompleteHosts.end(); hostI++) { hsi = *hostI; - FPR = hsi->target->FPR; + FPR = hsi->FPR; log_write(LOG_NORMAL|LOG_SKID_NOXLT|LOG_STDOUT, "No OS matches for %s by new os scan system.\n\nTCP/IP fingerprint:\n%s", hsi->target->targetipstr(), mergeFPs(FPR->FPs, FPR->numFPs, true, - hsi->target->v4hostip(), hsi->target->distance, + hsi->target->TargetSockAddr(), hsi->target->distance, hsi->target->distance_calculation_method, hsi->target->MACAddress(), FPR->osscan_opentcpport, FPR->osscan_closedtcpport, @@ -871,7 +872,7 @@ static int expireUnmatchedHosts(OsScanInfo *OSI, list *unMatch if (HOS->target->FPR->OmitSubmissionFP()) max_tries = min(max_tries, STANDARD_OS2_TRIES); - if (HOS->target->FPR->numFPs >= max_tries) { + if (HOS->FPR->numFPs >= max_tries) { /* We've done all the OS2 tries we're going to do ... move this to unMatchedHosts */ HOS->target->stopTimeOutClock(&now); @@ -886,108 +887,6 @@ static int expireUnmatchedHosts(OsScanInfo *OSI, list *unMatch } -/* You should call os_scan2 rather than this function, as that version handles - chunking so you don't do too many targets in parallel */ -static int os_scan_2(vector &Targets) { - // Hosts which haven't matched and have been removed from - // incompleteHosts because they have exceeded the number of - // retransmissions the host is allowed. - list unMatchedHosts; - int itry; - - if (Targets.size() == 0) { - return 1; - } - - init_perf_values(); - - OsScanInfo OSI(Targets); - if (OSI.numIncompleteHosts() == 0) { - /* no one will be scanned */ - return 1; - } - OSI.starttime = o.TimeSinceStart(); - startTimeOutClocks(&OSI); - - HostOsScan HOS(Targets[0]); - - itry = 0; - - - - begin_sniffer(&HOS, Targets); /* initial the pcap session handler in HOS */ - while(OSI.numIncompleteHosts() != 0) { - if (itry > 0) sleep(1); - if (itry == 3) usleep(1500000); /* Try waiting a little longer just in case it matters */ - if (o.verbose) { - char targetstr[128]; - bool plural = (OSI.numIncompleteHosts() != 1); - if (!plural) { - (*(OSI.incompleteHosts.begin()))->target->NameIP(targetstr, sizeof(targetstr)); - } else Snprintf(targetstr, sizeof(targetstr), "%d hosts", (int) OSI.numIncompleteHosts()); - log_write(LOG_STDOUT, "%s OS detection (try #%d) against %s\n", (itry == 0)? "Initiating" : "Retrying", itry + 1, targetstr); - log_flush_all(); - } - startRound(&OSI, &HOS, itry); - doSeqTests(&OSI, &HOS); - doTUITests(&OSI, &HOS); - endRound(&OSI, &HOS, itry); - expireUnmatchedHosts(&OSI, &unMatchedHosts); - itry++; - } - - /* Now move the unMatchedHosts array back to IncompleteHosts */ - if (!unMatchedHosts.empty()) - OSI.incompleteHosts.splice(OSI.incompleteHosts.begin(), unMatchedHosts); - - if (OSI.numIncompleteHosts()) { - /* For host that doesn't have a perfect match, we do the following - things. */ - - /* Find the most matching item in the db. */ - findBestFPs(&OSI); - - /* Print the fp in debug mode. - Normally let output.cc to print the FP. */ - if(o.debugging > 1) - printFP(&OSI); - } - - return 0; -} - - -/* This is the primary OS detection function. If many Targets are - passed in (the threshold is based on timing level), they are - processed as smaller groups to improve accuracy */ -void os_scan2(vector &Targets) { - unsigned int max_os_group_sz = 20; - double fudgeratio = 1.2; /* Allow a slightly larger final group rather than finish with a tiny one */ - vector tmpTargets; - unsigned int startidx = 0; - - if (o.timing_level == 4) - max_os_group_sz = (unsigned int) (max_os_group_sz * 1.5); - - if (o.timing_level > 4 || Targets.size() <= max_os_group_sz * fudgeratio) { - os_scan_2(Targets); - return; - } - - /* We need to split it up */ - while(startidx < Targets.size()) { - int diff = Targets.size() - startidx; - if (diff > max_os_group_sz * fudgeratio) { - diff = max_os_group_sz; - } - tmpTargets.assign(Targets.begin() + startidx, Targets.begin() + startidx + diff); - os_scan_2(tmpTargets); - startidx += diff; - } - return; -} - - /****************************************************************************** * Implementation of class OFProbe * ******************************************************************************/ @@ -3364,12 +3263,14 @@ HostOsScanInfo::HostOsScanInfo(Target *t, OsScanInfo *OsSI) { OSI = OsSI; FPs = (FingerPrint **) safe_zalloc(o.maxOSTries() * sizeof(FingerPrint *)); - FP_matches = (FingerPrintResults *) safe_zalloc(o.maxOSTries() * sizeof(FingerPrintResults)); + FP_matches = (FingerPrintResultsIPv4 *) safe_zalloc(o.maxOSTries() * sizeof(FingerPrintResultsIPv4)); timedOut = false; isCompleted = false; - if (target->FPR == NULL) - target->FPR = new FingerPrintResults; + if (target->FPR == NULL) { + this->FPR = new FingerPrintResultsIPv4; + target->FPR = this->FPR; + } target->osscanSetFlag(OS_PERF); hss = new HostOsScanStats(t); @@ -3521,3 +3422,180 @@ int OsScanInfo::removeCompletedHosts() { } return hostsRemoved; } + +/****************************************************************************** + * Implementation of class OSScan() * + ******************************************************************************/ + +/* Constructor */ +OSScan::OSScan() { + this->reset(); + return; +} + +/* Destructor */ +OSScan::~OSScan() { + return; +} + +/* Function that initializes internal variables */ +void OSScan::reset(){ + +} + + +/* This function takes a group of targets and divides it in chunks if there are + * too many to be processed at the same time. The threshold is based on Nmap's + * timing level (when timing level is above 4, no chunking is performed). + * The reason targets are processed in smaller groups is to improve accuracy. */ +int OSScan::chunk_and_do_scan(vector &Targets, int family) { + unsigned int max_os_group_sz = 20; + double fudgeratio = 1.2; /* Allow a slightly larger final group rather than finish with a tiny one */ + vector tmpTargets; + unsigned int startidx = 0; + + if (o.timing_level == 4) + max_os_group_sz = (unsigned int) (max_os_group_sz * 1.5); + + if (o.timing_level > 4 || Targets.size() <= max_os_group_sz * fudgeratio) { + if(family==AF_INET6) + os_scan_ipv6(Targets); + else + os_scan_ipv4(Targets); + return OP_SUCCESS; + } + + /* We need to split it up */ + while(startidx < Targets.size()) { + int diff = Targets.size() - startidx; + if (diff > max_os_group_sz * fudgeratio) { + diff = max_os_group_sz; + } + tmpTargets.assign(Targets.begin() + startidx, Targets.begin() + startidx + diff); + if(family==AF_INET6) + os_scan_ipv6(Targets); + else + os_scan_ipv4(Targets); + startidx += diff; + } + return OP_SUCCESS; +} + + +/* Performs the OS detection for IPv4 hosts. This method should not be called + * directly. os_scan() should be used instead, as it handles chunking so + * you don't do too many targets in parallel */ +int OSScan::os_scan_ipv4(vector &Targets) { + int itry=0; + /* Hosts which haven't matched and have been removed from incompleteHosts because + * they have exceeded the number of retransmissions the host is allowed. */ + list unMatchedHosts; + + /* Check we have at least one target*/ + if (Targets.size() == 0) { + return OP_FAILURE; + } + + /* Init the necessary objects to perform the detection */ + init_perf_values(); + + OsScanInfo OSI(Targets); + if (OSI.numIncompleteHosts() == 0) { + /* no one will be scanned */ + return OP_FAILURE; + } + OSI.starttime = o.TimeSinceStart(); + startTimeOutClocks(&OSI); + + HostOsScan HOS(Targets[0]); + + /* Initialize the pcap session handler in HOS */ + begin_sniffer(&HOS, Targets); + while(OSI.numIncompleteHosts() != 0) { + if (itry > 0) sleep(1); + if (itry == 3) usleep(1500000); /* Try waiting a little longer just in case it matters */ + if (o.verbose) { + char targetstr[128]; + bool plural = (OSI.numIncompleteHosts() != 1); + if (!plural) { + (*(OSI.incompleteHosts.begin()))->target->NameIP(targetstr, sizeof(targetstr)); + } else Snprintf(targetstr, sizeof(targetstr), "%d hosts", (int) OSI.numIncompleteHosts()); + log_write(LOG_STDOUT, "%s OS detection (try #%d) against %s\n", (itry == 0)? "Initiating" : "Retrying", itry + 1, targetstr); + log_flush_all(); + } + startRound(&OSI, &HOS, itry); + doSeqTests(&OSI, &HOS); + doTUITests(&OSI, &HOS); + endRound(&OSI, &HOS, itry); + expireUnmatchedHosts(&OSI, &unMatchedHosts); + itry++; + } + + /* Now move the unMatchedHosts array back to IncompleteHosts */ + if (!unMatchedHosts.empty()) + OSI.incompleteHosts.splice(OSI.incompleteHosts.begin(), unMatchedHosts); + + if (OSI.numIncompleteHosts()) { + /* For hosts that don't have a perfect match, find the closest fingerprint + * in the DB and, if we are in debugging mode, print them. */ + findBestFPs(&OSI); + if(o.debugging > 1) + printFP(&OSI); + } + + return OP_SUCCESS; +} + + +/* Performs the OS detection for IPv6 hosts. This method should not be called + * directly. os_scan() should be used instead, as it handles chunking so + * you don't do too many targets in parallel */ +int OSScan::os_scan_ipv6(vector &Targets) { + + /* Object instantiation */ + FPEngine6 fp6; + + /* Safe checks. */ + if (Targets.size() == 0) { + return OP_FAILURE; + } + + return fp6.os_scan(Targets); +} + + +/* This function performs the OS detection. It processes the supplied list of + * targets and classifies it into two groups: IPv4 and IPv6 targets. Then, + * OS detection is carried out for those two separate groups. It returns + * OP_SUCCESS on success or OP_FAILURE in case of error. */ +int OSScan::os_scan(vector &Targets){ + vector ip4_targets; + vector ip6_targets; + int res4=OP_SUCCESS, res6=OP_SUCCESS; + + /* Make sure we have at least one target */ + if(Targets.size()<=0) + return OP_FAILURE; + + /* Classify targets into two groups: IPv4 and IPv6 */ + for(size_t i=0; iaf()==AF_INET6) + ip6_targets.push_back(Targets[i]); + else + ip4_targets.push_back(Targets[i]); + } + + /* Do IPv4 OS Detection */ + if( ip4_targets.size()>0 ) + res4=this->os_scan_ipv4(ip4_targets); + + /* Do IPv6 OS Detection */ + if( ip6_targets.size()>0 ) + res6=this->os_scan_ipv6(ip6_targets); + + /* If both scans were succesful, return OK */ + if(res4==OP_SUCCESS && res6==OP_SUCCESS) + return OP_SUCCESS; + else + return OP_FAILURE; +} diff --git a/osscan2.h b/osscan2.h index 865fb66b74..80ede3d46b 100644 --- a/osscan2.h +++ b/osscan2.h @@ -511,13 +511,34 @@ class HostOsScanInfo { ~HostOsScanInfo(); Target *target; /* The target */ + FingerPrintResultsIPv4 *FPR; OsScanInfo *OSI; /* The OSI which contains this HostOsScanInfo */ FingerPrint **FPs; /* Fingerprints of the host */ - FingerPrintResults *FP_matches; /* Fingerprint-matching results */ + FingerPrintResultsIPv4 *FP_matches; /* Fingerprint-matching results */ bool timedOut; /* Did it time out? */ bool isCompleted; /* Has the OS detection been completed? */ HostOsScanStats *hss; /* Scan status of the host in one scan round */ }; + +/** This is the class that performs OS detection (both IPv4 and IPv6). + * Using it is simple, just call os_scan() passing a list of targets. + * The results of the detection will be stored inside the supplied + * target objects. */ +class OSScan { + + private: + int ip_ver; /* IP version for the OS Scan (4 or 6) */ + int chunk_and_do_scan(vector &Targets, int family); + int os_scan_ipv4(vector &Targets); + int os_scan_ipv6(vector &Targets); + + public: + OSScan(); + ~OSScan(); + void reset(); + int os_scan(vector &Targets); +}; + #endif /*OSSCAN2_H*/ diff --git a/output.cc b/output.cc index 57ca8f31fa..4801c6b984 100644 --- a/output.cc +++ b/output.cc @@ -114,6 +114,7 @@ #include #include #include +#include /* Workaround for lack of namespace std on HP-UX 11.00 */ namespace std {}; @@ -1499,7 +1500,7 @@ static void printosclassificationoutput(const struct // Now to create the fodder for normal output for (classno = 0; classno < OSR->OSC_num_matches; classno++) { /* We have processed enough if any of the following are true */ - if ((!guess && OSR->OSC_Accuracy[classno] < 1.0) || + if ((!guess && classno >= OSR->OSC_num_perfect_matches) || OSR->OSC_Accuracy[classno] <= OSR->OSC_Accuracy[0] - 0.1 || (OSR->OSC_Accuracy[classno] < 1.0 && classno > 9)) break; @@ -1563,14 +1564,14 @@ static void printosclassificationoutput(const struct log_write(LOG_PLAIN, "Device type: "); for (classno = 0; classno < numtypes; classno++) log_write(LOG_PLAIN, "%s%s", types[classno], (classno < numtypes - 1) ? "|" : ""); - log_write(LOG_PLAIN, "\nRunning%s: ", (familyaccuracy[0] < 1.0) ? " (JUST GUESSING)" : ""); + log_write(LOG_PLAIN, "\nRunning%s: ", OSR->OSC_num_perfect_matches == 0 ? " (JUST GUESSING)" : ""); for (familyno = 0; familyno < numfamilies; familyno++) { if (familyno > 0) log_write(LOG_PLAIN, ", "); log_write(LOG_PLAIN, "%s", fullfamily[familyno]); if (*familygenerations[familyno]) log_write(LOG_PLAIN, " %s", familygenerations[familyno]); - if (familyaccuracy[familyno] < 1.0) + if (familyno >= OSR->OSC_num_perfect_matches) log_write(LOG_PLAIN, " (%.f%%)", floor(familyaccuracy[familyno] * 100)); } @@ -1609,28 +1610,187 @@ void printmacinfo(Target *currenths) { /* A convenience wrapper around mergeFPs. */ -static const char *merge_fpr(const FingerPrintResults *FPR, - const Target *currenths, - bool isGoodFP, bool wrapit) { - return mergeFPs(FPR->FPs, FPR->numFPs, isGoodFP, currenths->v4hostip(), +const char *FingerPrintResultsIPv4::merge_fpr(const Target *currenths, + bool isGoodFP, bool wrapit) const { + return mergeFPs(this->FPs, this->numFPs, isGoodFP, currenths->TargetSockAddr(), currenths->distance, currenths->distance_calculation_method, - currenths->MACAddress(), FPR->osscan_opentcpport, - FPR->osscan_closedtcpport, FPR->osscan_closedudpport, + currenths->MACAddress(), this->osscan_opentcpport, + this->osscan_closedtcpport, this->osscan_closedudpport, wrapit); } +/* Run-length encode a string in chunks of two bytes. The output sequence + AA{n} means to repeat AA n times. The input must not contain '{' or '}' + characters. */ +static std::string run_length_encode(const std::string &s) { + std::ostringstream result; + const char *p, *q; + unsigned int reps; + + p = s.c_str(); + while (*p != '\0' && *(p + 1) != '\0') { + for (q = p + 2; *q == *p && *(q + 1) == *(p + 1); q += 2) + ; + reps = (q - p) / 2; + if (reps < 3) + result << std::string(p, q); + else + result << std::string(p, 2) << "{" << reps << "}"; + p = q; + } + if (*p != '\0') + result << std::string(p); + + return result.str(); +} + +static std::string wrap(const std::string &s) { + const static char *prefix = "OS:"; + std::string t, buf; + int i, len, prefixlen; + size_t p; + + t = s; + /* Remove newlines. */ + p = 0; + while ((p = t.find("\n", p)) != std::string::npos) + t.erase(p, 1); + + len = t.size(); + prefixlen = strlen(prefix); + assert(FP_RESULT_WRAP_LINE_LEN > prefixlen); + for (i = 0; i < len; i += FP_RESULT_WRAP_LINE_LEN - prefixlen) { + buf.append(prefix); + buf.append(t, i, FP_RESULT_WRAP_LINE_LEN - prefixlen); + buf.append("\n"); + } + + return buf; +} + +static void scrub_packet(PacketElement *pe, unsigned char fill) { + unsigned char fillbuf[16]; + + memset(fillbuf, fill, sizeof(fillbuf)); + for (; pe != NULL; pe = pe->getNextElement()) { + if (pe->protocol_id() == HEADER_TYPE_IPv6) { + IPv6Header *ipv6 = (IPv6Header *) pe; + ipv6->setSourceAddress(fillbuf); + ipv6->setDestinationAddress(fillbuf); + } else if (pe->protocol_id() == HEADER_TYPE_ICMPv6) { + ICMPv6Header *icmpv6 = (ICMPv6Header *) pe; + in6_addr *addr = (in6_addr *) fillbuf; + if (icmpv6->getType() == ICMPV6_NEIGHBOR_ADVERTISEMENT) + icmpv6->setTargetAddress(*addr); + } + } +} + +static std::string get_scrubbed_buffer(const FPResponse *resp) { + std::ostringstream result; + PacketElement *scrub1, *scrub2; + u8 *buf1, *buf2; + int len1, len2; + unsigned int i; + + scrub1 = PacketParser::split(resp->buf, resp->len); + assert(scrub1 != NULL); + scrub_packet(scrub1, 0x00); + + scrub2 = PacketParser::split(resp->buf, resp->len); + assert(scrub2 != NULL); + scrub_packet(scrub2, 0xFF); + + buf1 = scrub1->getBinaryBuffer(&len1); + buf2 = scrub2->getBinaryBuffer(&len2); + + assert(resp->len == (unsigned int) len1); + assert(resp->len == (unsigned int) len2); + + result.fill('0'); + result << std::hex; + for (i = 0; i < resp->len; i++) { + if (resp->buf[i] == buf1[i] && resp->buf[i] == buf2[i]) { + result.width(2); + result << (unsigned int) resp->buf[i]; + } else { + result << "XX"; + } + } + + free(buf1); + free(buf2); + PacketParser::freePacketChain(scrub1); + PacketParser::freePacketChain(scrub2); + + return result.str(); +} + +const char *FingerPrintResultsIPv6::merge_fpr(const Target *currenths, + bool isGoodFP, bool wrapit) const { + static char str[10240]; + const FingerPrintResultsIPv6 *FPR; + std::ostringstream result; + std::string output; + unsigned int i; + + /* Write the SCAN line. */ + WriteSInfo(str, sizeof(str), isGoodFP, "6", currenths->TargetSockAddr(), + currenths->distance, currenths->distance_calculation_method, + currenths->MACAddress(), this->osscan_opentcpport, + this->osscan_closedtcpport, this->osscan_closedudpport); + result << str << "\n"; + + FPR = (FingerPrintResultsIPv6 *) currenths->FPR; + assert(FPR->begin_time.tv_sec != 0); + for (i = 0; i < sizeof(FPR->fp_responses) / sizeof(FPR->fp_responses[0]); i++) { + const FPResponse *resp; + std::string scrubbed; + + resp = this->fp_responses[i]; + if (resp == NULL) + continue; + scrubbed = get_scrubbed_buffer(resp); + if (wrapit) + scrubbed = run_length_encode(scrubbed); + result << resp->probe_id << "(P=" << scrubbed; + assert(resp->senttime.tv_sec != 0); + result << "%ST=" << TIMEVAL_FSEC_SUBTRACT(resp->senttime, FPR->begin_time); + assert(resp->rcvdtime.tv_sec != 0); + result << "%RT=" << TIMEVAL_FSEC_SUBTRACT(resp->rcvdtime, FPR->begin_time); + result << ")\n"; + } + + result << "EXTRA("; + result << "FL="; + result.fill('0'); + result << std::hex; + result.width(5); + result << FPR->flow_label; + result << ")\n"; + + output = result.str(); + if (wrapit) { + output = wrap(output); + } + + Strncpy(str, output.c_str(), sizeof(str)); + + return str; +} + static void write_merged_fpr(const FingerPrintResults *FPR, const Target *currenths, bool isGoodFP, bool wrapit) { log_write(LOG_NORMAL | LOG_SKID_NOXLT | LOG_STDOUT, "TCP/IP fingerprint:\n%s\n", - merge_fpr(FPR, currenths, isGoodFP, wrapit)); + FPR->merge_fpr(currenths, isGoodFP, wrapit)); /* Added code here to print fingerprint to XML file any time it would be printed to any other output format */ xml_open_start_tag("osfingerprint"); - xml_attribute("fingerprint", "%s", merge_fpr(FPR, currenths, isGoodFP, wrapit)); + xml_attribute("fingerprint", "%s", FPR->merge_fpr(currenths, isGoodFP, wrapit)); xml_close_empty_tag(); xml_newline(); } @@ -1691,22 +1851,22 @@ void printosscanoutput(Target *currenths) { /* Success, not too many perfect matches. */ if (FPR->num_perfect_matches > 0) { /* Some perfect matches. */ - for (i = 0; FPR->accuracy[i] == 1; i++) { + for (i = 0; i < FPR->num_perfect_matches; i++) { xml_open_start_tag("osmatch"); - xml_attribute("name", "%s", FPR->prints[i]->OS_name); - xml_attribute("accuracy", "100"); - xml_attribute("line", "%d", FPR->prints[i]->line); + xml_attribute("name", "%s", FPR->matches[i]->OS_name); + xml_attribute("accuracy", "%d", (int) (FPR->accuracy[i] * 100)); + xml_attribute("line", "%d", FPR->matches[i]->line); xml_close_empty_tag(); xml_newline(); } - log_write(LOG_MACHINE, "\tOS: %s", FPR->prints[0]->OS_name); - for (i = 1; FPR->accuracy[i] == 1; i++) - log_write(LOG_MACHINE, "|%s", FPR->prints[i]->OS_name); + log_write(LOG_MACHINE, "\tOS: %s", FPR->matches[0]->OS_name); + for (i = 1; i < FPR->num_perfect_matches; i++) + log_write(LOG_MACHINE, "|%s", FPR->matches[i]->OS_name); - log_write(LOG_PLAIN, "OS details: %s", FPR->prints[0]->OS_name); - for (i = 1; FPR->accuracy[i] == 1; i++) - log_write(LOG_PLAIN, ", %s", FPR->prints[i]->OS_name); + log_write(LOG_PLAIN, "OS details: %s", FPR->matches[0]->OS_name); + for (i = 1; i < FPR->num_perfect_matches; i++) + log_write(LOG_PLAIN, ", %s", FPR->matches[i]->OS_name); log_write(LOG_PLAIN, "\n"); if (o.debugging || o.verbose > 1) @@ -1721,17 +1881,17 @@ void printosscanoutput(Target *currenths) { /* Print the best guesses available */ for (i = 0; i < 10 && i < FPR->num_matches && FPR->accuracy[i] > FPR->accuracy[0] - 0.10; i++) { xml_open_start_tag("osmatch"); - xml_attribute("name", "%s", FPR->prints[i]->OS_name); + xml_attribute("name", "%s", FPR->matches[i]->OS_name); xml_attribute("accuracy", "%d", (int) (FPR->accuracy[i] * 100)); - xml_attribute("line", "%d", FPR->prints[i]->line); + xml_attribute("line", "%d", FPR->matches[i]->line); xml_close_empty_tag(); xml_newline(); } log_write(LOG_PLAIN, "Aggressive OS guesses: %s (%.f%%)", - FPR->prints[0]->OS_name, floor(FPR->accuracy[0] * 100)); + FPR->matches[0]->OS_name, floor(FPR->accuracy[0] * 100)); for (i = 1; i < 10 && FPR->num_matches > i && FPR->accuracy[i] > FPR->accuracy[0] - 0.10; i++) - log_write(LOG_PLAIN, ", %s (%.f%%)", FPR->prints[i]->OS_name, floor(FPR->accuracy[i] * 100)); + log_write(LOG_PLAIN, ", %s (%.f%%)", FPR->matches[i]->OS_name, floor(FPR->accuracy[i] * 100)); log_write(LOG_PLAIN, "\n"); } diff --git a/todo/nmap.txt b/todo/nmap.txt index 459fd8e9da..69e3eda68f 100644 --- a/todo/nmap.txt +++ b/todo/nmap.txt @@ -371,6 +371,14 @@ o [Nsock] Consider adding server support to Nsock so it can accept followed by a nonblocking accept(). Then Nping gives the SD's to Nsock to manage. +o Consider implementing both global and per-host congestion control in + the IPv6 OS detection engine. Currently it handles congestion globally + (one CWND and SSTHRESH shared by all hosts). This works fine but it + may not be the most efficient approach: if the congestion is not + in our network segment but in a target's and we are os-scanning + hosts in different networks, then all hosts get "penalized" because + there is congestion in another network, not in theirs. + o [Nsock] Consider implementing a nsock_pcap_close() function or making nsp_delete() call pcap_close() when pcap IODs are used. Currently valgrind warns about a socket descriptor left opened (at least in Nping).