Index: NmapOps.cc =================================================================== --- NmapOps.cc (revision 34903) +++ NmapOps.cc (working copy) @@ -163,6 +163,10 @@ free(ipoptions); ipoptions = NULL; } + if (tcpoptions) { + free(tcpoptions); + tcpoptions = NULL; + } if (portlist) { free(portlist); portlist = NULL; Index: NmapOps.h =================================================================== --- NmapOps.h (revision 34903) +++ NmapOps.h (working copy) @@ -399,6 +399,9 @@ int ipopt_firsthop; // offset in ipoptions where is first hop for source/strict routing int ipopt_lasthop; // offset in ipoptions where is space for targets ip for source/strict routing + char *tcpoptions; + unsigned int tcpoptionslen; + // Statistics Options set in nmap.cc int numhosts_scanned; int numhosts_up; Index: idle_scan.cc =================================================================== --- idle_scan.cc (revision 34903) +++ idle_scan.cc (working copy) @@ -270,6 +270,15 @@ if (!ack) ack = get_random_u32(); + u8 *tcpops; + int tcpopslen; + if (o.tcpoptionslen) { + tcpops = (u8 *) o.tcpoptions; + tcpopslen = o.tcpoptionslen; + } else { + tcpops = (u8 *) TCP_SYN_PROBE_OPTIONS; + tcpopslen = TCP_SYN_PROBE_OPTIONS_LEN; + } do { gettimeofday(&tv_sent[tries], NULL); @@ -282,8 +291,7 @@ o.ipoptions, o.ipoptionslen, base_port + tries, proxy->probe_port, seq_base + (packet_send_count++ * 500) + 1, ack, 0, TH_SYN | TH_ACK, 0, 0, - (u8 *) TCP_SYN_PROBE_OPTIONS, TCP_SYN_PROBE_OPTIONS_LEN, - NULL, 0); + tcpops, tcpopslen, NULL, 0); else { ipv6_packet = build_tcp_raw_ipv6(proxy->host.v6sourceip(), proxy->host.v6hostip(), 0x00, 0x0000, @@ -290,9 +298,7 @@ o.ttl, base_port + tries, proxy->probe_port, seq_base + (packet_send_count++ * 500) + 1, ack, 0, TH_SYN | TH_ACK, 0, 0, - (u8 *) TCP_SYN_PROBE_OPTIONS, TCP_SYN_PROBE_OPTIONS_LEN, - NULL, 0, - &packetlen); + tcpops, tcpopslen, NULL, 0, &packetlen); proxy->host.TargetSockAddr(&ss, &sslen); res = send_ip_packet(proxy->rawsd, proxy->ethptr, &ss, ipv6_packet, packetlen); if (res == -1) @@ -709,6 +715,16 @@ /* Yahoo! It is finally time to send our probes! */ + u8 *tcpops; + int tcpopslen; + if (o.tcpoptionslen) { + tcpops = (u8 *) o.tcpoptions; + tcpopslen = o.tcpoptionslen; + } else { + tcpops = (u8 *) TCP_SYN_PROBE_OPTIONS; + tcpopslen = TCP_SYN_PROBE_OPTIONS_LEN; + } + while (probes_sent < NUM_IPID_PROBES) { if (o.scan_delay) enforce_scan_delay(NULL); @@ -728,8 +744,7 @@ o.ipoptions, o.ipoptionslen, o.magic_port + probes_sent + 1, proxy->probe_port, sequence_base + probes_sent + 1, ack, 0, TH_SYN | TH_ACK, 0, 0, - (u8 *) TCP_SYN_PROBE_OPTIONS, TCP_SYN_PROBE_OPTIONS_LEN, - NULL, 0); + tcpops, tcpopslen, NULL, 0); else if (o.af() == AF_INET6) { ipv6_packet = build_tcp_raw_ipv6(proxy->host.v6sourceip(), proxy->host.v6hostip(), 0x00, 0x0000, @@ -736,9 +751,7 @@ o.ttl, o.magic_port + probes_sent + 1, proxy->probe_port, sequence_base + probes_sent + 1, ack, 0, TH_SYN | TH_ACK, 0, 0, - (u8 *) TCP_SYN_PROBE_OPTIONS, TCP_SYN_PROBE_OPTIONS_LEN, - NULL, 0, - &packetlen); + tcpops, tcpopslen, NULL, 0, &packetlen); res = send_ip_packet(proxy->rawsd, proxy->ethptr, &ss, ipv6_packet, packetlen); if (res == -1) fatal("Error occurred while trying to send IPv6 packet"); @@ -911,6 +924,7 @@ behind an egress filter or other measure that prevents this sort of sp00fery */ /* this behavior gets quite common in IPv6 so now its even more important to check */ + if (target->v4hostip() || target->v6hostip()) { for (probes_sent = 0; probes_sent < 4; probes_sent++) { if (probes_sent != 0) @@ -922,8 +936,7 @@ o.ipoptions, o.ipoptionslen, o.magic_port, proxy->probe_port, sequence_base + probes_sent + 1, ack, 0, TH_SYN | TH_ACK, 0, 0, - (u8 *) TCP_SYN_PROBE_OPTIONS, - TCP_SYN_PROBE_OPTIONS_LEN, NULL, 0); + tcpops, tcpopslen, NULL, 0); } else { ipv6_packet = build_tcp_raw_ipv6(target->v6hostip(), proxy->host.v6hostip(), 0x00, 0x0000, @@ -930,9 +943,7 @@ o.ttl, o.magic_port, proxy->probe_port, sequence_base + probes_sent + 1, ack, 0, TH_SYN | TH_ACK, 0, 0, - (u8 *) TCP_SYN_PROBE_OPTIONS, - TCP_SYN_PROBE_OPTIONS_LEN, NULL, 0, - &packetlen); + tcpops, tcpopslen, NULL, 0, &packetlen); res = send_ip_packet(proxy->rawsd, proxy->ethptr, &ss, ipv6_packet, packetlen); if (res == -1) fatal("Error occurred while trying to send IPv6 packet "); @@ -1090,6 +1101,17 @@ but doing it the straightforward way (using the same decoys as we use in probing the proxy box is risky. I'll have to think about this more. */ + + u8 *tcpops; + int tcpopslen; + if (o.tcpoptionslen) { + tcpops = (u8 *) o.tcpoptions; + tcpopslen = o.tcpoptionslen; + } else { + tcpops = (u8 *) TCP_SYN_PROBE_OPTIONS; + tcpopslen = TCP_SYN_PROBE_OPTIONS_LEN; + } + if (o.af() == AF_INET ) { send_tcp_raw(proxy->rawsd, eth.ethsd ? ð : NULL, proxy->host.v4hostip(), target->v4hostip(), @@ -1096,15 +1118,13 @@ o.ttl, false, o.ipoptions, o.ipoptionslen, proxy->probe_port, ports[pr0be], seq, 0, 0, TH_SYN, 0, 0, - (u8 *) TCP_SYN_PROBE_OPTIONS, TCP_SYN_PROBE_OPTIONS_LEN, - o.extra_payload, o.extra_payload_length); + tcpops, tcpopslen, o.extra_payload, o.extra_payload_length); } else { packet = build_tcp_raw_ipv6(proxy->host.v6hostip(), target->v6hostip(), 0x00, 0x0000, o.ttl, proxy->probe_port, ports[pr0be], seq, 0, 0, TH_SYN, 0, 0, - (u8 *) TCP_SYN_PROBE_OPTIONS, TCP_SYN_PROBE_OPTIONS_LEN, - o.extra_payload, o.extra_payload_length, + tcpops, tcpopslen, o.extra_payload, o.extra_payload_length, &packetlen); res = send_ip_packet(proxy->rawsd, eth.ethsd ? ð : NULL, &ss, packet, packetlen); if (res == -1) Index: nmap.cc =================================================================== --- nmap.cc (revision 34903) +++ nmap.cc (working copy) @@ -670,6 +670,8 @@ #endif {"ip_options", required_argument, 0, 0}, {"ip-options", required_argument, 0, 0}, + /* tcp_options deliberately not there */ + {"tcp-options", required_argument, 0, 0}, {"min_rate", required_argument, 0, 0}, {"min-rate", required_argument, 0, 0}, {"max_rate", required_argument, 0, 0}, @@ -829,6 +831,7 @@ if (nsock_set_default_engine(optarg) < 0) fatal("Unknown or non-available engine: %s", optarg); } else if ((optcmp(long_options[option_index].name, "proxies") == 0) || (optcmp(long_options[option_index].name, "proxy") == 0)) { + printf("test\n"); if (nsock_proxychain_new(optarg, &o.proxy_chain, NULL) < 0) fatal("Invalid proxy chain specification"); } else if (optcmp(long_options[option_index].name, "osscan-limit") == 0) { @@ -973,6 +976,8 @@ fatal("Ip options can't be more than 40 bytes long"); if (o.ipoptionslen % 4 != 0) fatal("Ip options must be multiple of 4 (read length is %i bytes)", o.ipoptionslen); + } else if (optcmp(long_options[option_index].name, "tcp-options") == 0) { + o.tcpoptions = cstring_unescape(strdup(optarg), &o.tcpoptionslen); } else if (strcmp(long_options[option_index].name, "traceroute") == 0) { o.traceroute = true; } else if (strcmp(long_options[option_index].name, "reason") == 0) { Index: nping/configure =================================================================== --- nping/configure (revision 34903) +++ nping/configure (working copy) @@ -2229,6 +2229,10 @@ + + + + # Check whether --with-localdirs was given. if test "${with_localdirs+set}" = set; then : withval=$with_localdirs; case "$with_localdirs" in Index: scan_engine_raw.cc =================================================================== --- scan_engine_raw.cc (revision 34903) +++ scan_engine_raw.cc (working copy) @@ -1307,8 +1307,13 @@ seq = seq32_encode(USI, tryno, pingseq); if (pspec->pd.tcp.flags & TH_SYN) { - tcpops = (u8 *) TCP_SYN_PROBE_OPTIONS; - tcpopslen = TCP_SYN_PROBE_OPTIONS_LEN; + if (o.tcpoptionslen) { + tcpops = (u8 *) o.tcpoptions; + tcpopslen = o.tcpoptionslen; + } else { + tcpops = (u8 *) TCP_SYN_PROBE_OPTIONS; + tcpopslen = TCP_SYN_PROBE_OPTIONS_LEN; + } } if (hss->target->af() == AF_INET) { Index: traceroute.cc =================================================================== --- traceroute.cc (revision 34903) +++ traceroute.cc (working copy) @@ -736,17 +736,22 @@ : Probe(host, pspec, ttl) { } unsigned char *build_packet(const struct sockaddr_storage *source, u32 *len) const { - const char *tcpopts; - int tcpoptslen; + u8 *tcpops; + int tcpopslen; u32 ack; - tcpopts = NULL; - tcpoptslen = 0; + tcpops = NULL; + tcpopslen = 0; ack = 0; if ((pspec.pd.tcp.flags & TH_SYN) == TH_SYN) { /* MSS 1460 bytes. */ - tcpopts = TCP_SYN_PROBE_OPTIONS; - tcpoptslen = TCP_SYN_PROBE_OPTIONS_LEN; + if (o.tcpoptionslen) { + tcpops = (u8 *) o.tcpoptions; + tcpopslen = o.tcpoptionslen; + } else { + tcpops = (u8 *) TCP_SYN_PROBE_OPTIONS; + tcpopslen = TCP_SYN_PROBE_OPTIONS_LEN; + } } else if ((pspec.pd.tcp.flags & TH_ACK) == TH_ACK) { ack = get_random_u32(); } @@ -757,7 +762,7 @@ return build_tcp_raw(&sin->sin_addr, host->target->v4hostip(), ttl, get_random_u16(), get_random_u8(), false, NULL, 0, token ^ global_id, pspec.pd.tcp.dport, get_random_u32(), ack, 0x00, - pspec.pd.tcp.flags, get_random_u16(), 0, (const u8 *) tcpopts, tcpoptslen, + pspec.pd.tcp.flags, get_random_u16(), 0, (const u8 *) tcpops, tcpopslen, o.extra_payload, o.extra_payload_length, len); } else if (source->ss_family == AF_INET6) { const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) source; @@ -764,7 +769,7 @@ return build_tcp_raw_ipv6(&sin6->sin6_addr, host->target->v6hostip(), 0, 0, ttl, token ^ global_id, pspec.pd.tcp.dport, get_random_u32(), ack, 0x00, - pspec.pd.tcp.flags, get_random_u16(), 0, (const u8 *) tcpopts, tcpoptslen, + pspec.pd.tcp.flags, get_random_u16(), 0, (const u8 *) tcpops, tcpopslen, o.extra_payload, o.extra_payload_length, len); } else { fatal("Unknown address family %u in %s.", source->ss_family, __func__);