--- /dev/null
+#
+# Copyright (C) 2022 Alexander E. Patrakov
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# Special thanks to the Debian and Fedora projects for their hping3
+# packaging, elements of which (patches, list of dependencies, etc.) are
+# reused here.
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=hping3
+PKG_SOURCE_DATE:=2014-12-26
+PKG_SOURCE_VERSION:=3547c7691742c6eaa31f8402e0ccbb81387c1b99
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://github.com/antirez/hping
+PKG_MIRROR_HASH:=0d65eaa8e55ab10025fb2d615eb9567255288b3b9eb66465f54d0e1718bb80ad
+
+PKG_MAINTAINER:=Alexander E. Patrakov <patrakov@gmail.com>
+PKG_LICENSE:=GPL-2.0-only
+
+PKG_INSTALL:=1
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/hping3
+ SECTION:=net
+ CATEGORY:=Network
+ TITLE:=Active Network Smashing Tool
+ URL:=https://github.com/antirez/hping
+ DEPENDS:= +libpcap
+endef
+
+define Package/hping3/description
+ hping3 is a network tool able to send custom ICMP/UDP/TCP packets
+ and to display target replies like ping does with ICMP replies. It
+ handles fragmentation and arbitrary packet body and size, and can
+ be used to transfer files under supported protocols. Using hping3,
+ you can test firewall rules, perform (spoofed) port scanning, test
+ network performance using different protocols, do path MTU
+ discovery, perform traceroute-like actions under different
+ protocols, fingerprint remote operating systems, audit TCP/IP
+ stacks, etc. Tcl support is not included.
+endef
+
+define Package/hping3/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/hping3 $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,hping3))
--- /dev/null
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -9,8 +9,8 @@
+ CC= gcc
+ AR=/usr/bin/ar
+ RANLIB=/usr/bin/ranlib
+-CCOPT= -O2 -Wall @PCAP_INCLUDE@ @TCL_INC@ @USE_TCL@
+-DEBUG= -g
++CCOPT= $(CFLAGS) @PCAP_INCLUDE@ @TCL_INC@ @USE_TCL@
++DEBUG=
+ #uncomment the following if you need libpcap based build under linux
+ #(not raccomanded)
+ COMPILE_TIME=
+@@ -50,17 +50,13 @@ libars.a: $(ARSOBJ)
+ $(RANLIB) $@
+
+ hping3: byteorder.h $(OBJ)
+- $(CC) -o hping3 $(CCOPT) $(DEBUG) $(OBJ) -L/usr/local/lib $(PCAP) @SOLARISLIB@ @TCL_LIB@
++ $(CC) -o hping3 $(CCOPT) $(DEBUG) $(OBJ) $(PCAP) @SOLARISLIB@ @TCL_LIB@
+ @echo
+- ./hping3 -v
+ @echo "use \`make strip' to strip hping3 binary"
+ @echo "use \`make install' to install hping3"
+
+ hping3-static: byteorder.h $(OBJ)
+- $(CC) -static -o hping3-static $(CCOPT) $(DEBUG) $(OBJ) -L/usr/local/lib $(PCAP) @SOLARISLIB@ @TCL_LIB@ -ldl
+-
+-byteorder.h:
+- ./configure
++ $(CC) -static -o hping3-static $(CCOPT) $(DEBUG) $(OBJ) $(PCAP) @SOLARISLIB@ @TCL_LIB@ -ldl
+
+ .c.o:
+ $(CC) -c $(CCOPT) $(DEBUG) $(COMPILE_TIME) $<
+@@ -72,6 +68,8 @@ distclean:
+ rm -rf hping3 *.o byteorder byteorder.h systype.h Makefile libars.a .depend
+
+ install: hping3
++
++dont-install:
+ cp -f hping3 /usr/sbin/
+ chmod 755 /usr/sbin/hping3
+ ln -s /usr/sbin/hping3 /usr/sbin/hping
+--- /dev/null
++++ b/byteorder.h
+@@ -0,0 +1,15 @@
++
++#ifndef __BYTEORDER_H
++#define __BYTEORDER_H
++
++#if defined(__BYTE_ORDER__)
++ #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
++ #define __BIG_ENDIAN_BITFIELD
++ #else
++ #define __LITTLE_ENDIAN_BITFIELD
++ #endif
++#else
++ #error Byte order not set
++#endif
++
++#endif /* __BYTEORDER_H */
+--- a/configure
++++ b/configure
+@@ -1,5 +1,24 @@
+ #!/bin/sh
+
++# This fake configure script applies hard-coded settings for OpenWRT
++
++echo creating Makefile...
++sed -e "s^@PCAP@^PCAP=-lpcap^g" \
++ -e "s^@PCAP_INCLUDE@^^g" \
++ -e "s^@MANPATH@^/usr/share/man^g" \
++ -e "s^@SOLARISLIB@^^g" \
++ -e "s^@USE_TCL@^^g" \
++ -e "s^@TCL_INC@^^g" \
++ -e "s^@TCL_VER@^^g" \
++ -e "s^@TCL_LIB@^^g" \
++ <Makefile.in > Makefile
++
++echo now you can try \`make\'
++exit 0
++
++# Original file follows, to make the patch smaller
++#!/bin/sh
++
+ show_help()
+ {
+ echo configure help:
+--- /dev/null
++++ b/systype.h
+@@ -0,0 +1,6 @@
++#ifndef __SYSTYPE_H
++#define __SYSTYPE_H
++
++#define OSTYPE_LINUX
++
++#endif /* SYSTYPE_H */
--- /dev/null
+--- a/libpcap_stuff.c
++++ b/libpcap_stuff.c
+@@ -16,7 +16,7 @@
+ #include <string.h>
+ #include <stdlib.h>
+ #include <sys/ioctl.h>
+-#include <net/bpf.h>
++#include <pcap-bpf.h>
+ #include <pcap.h>
+
+ #include "globals.h"
+--- a/script.c
++++ b/script.c
+@@ -23,7 +23,7 @@
+ #include <sched.h>
+
+ #include <sys/ioctl.h>
+-#include <net/bpf.h>
++#include <pcap-bpf.h>
+ #include <pcap.h>
+
+ #include "release.h"
--- /dev/null
+Subject: Various spelling fixes.
+Author: Romain Francoise <rfrancoise@debian.org>
+Last-Updated: 2020-09-06
+
+--- a/antigetopt.c
++++ b/antigetopt.c
+@@ -142,7 +142,7 @@ chain_start:
+ #define UNK_LONG_ERRSTRING "unrecognized option `--%s'\n"
+ #define ARG_SHORT_ERRSTRING "option requires an argument -- %c\n"
+ #define ARG_LONG_ERRSTRING "option `--%s' requires an argument\n"
+-#define AMB_ERRSTRING "option `--%s' is ambiguos\n"
++#define AMB_ERRSTRING "option `--%s' is ambiguous\n"
+ #define IERR_ERRSTRING "internal error. ago_gnu_error() called with " \
+ "a bad error code (%d)\n"
+ void ago_gnu_error(char *pname, int error)
+--- a/statistics.c
++++ b/statistics.c
+@@ -30,7 +30,7 @@ void print_statistics(int signal_id)
+ lossrate = 100;
+
+ fprintf(stderr, "\n--- %s hping statistic ---\n", targetname);
+- fprintf(stderr, "%d packets tramitted, %d packets received, "
++ fprintf(stderr, "%d packets transmitted, %d packets received, "
+ "%d%% packet loss\n", sent_pkt, recv_pkt, lossrate);
+ if (out_of_sequence_pkt)
+ fprintf(stderr, "%d out of sequence packets received\n",
+--- a/ars.c
++++ b/ars.c
+@@ -361,7 +361,7 @@ void *ars_add_data(struct ars_packet *pk
+ static void *ptr = "zzappt"; /* we can't return NULL for size == 0 */
+
+ if (size < 0) {
+- ars_set_error(pkt, "Tryed to add a DATA layer with size < 0");
++ ars_set_error(pkt, "Tried to add a DATA layer with size < 0");
+ return NULL;
+ }
+ retval = ars_add_generic(pkt, size, ARS_TYPE_DATA);
--- /dev/null
+Subject: Fix "-N" command line argument
+Author: Guillaume Delacour <gui@iroqwa.org>
+Bug-Debian: http://bugs.debian.org/482844
+Last-Update: 2009-05-13
+
+--- a/docs/hping2.8
++++ b/docs/hping2.8
+@@ -343,7 +343,7 @@ options. If in doubt try
+ .I -N --id
+ Set ip->id field. Default id is random but if fragmentation is turned on
+ and id isn't specified it will be
+-.BR "getpid() & 0xFF" ,
++.BR "getpid() & 0xFFFF" ,
+ to implement a better solution is in TODO list.
+ .TP
+ .I -H --ipproto
+@@ -714,4 +714,4 @@ On solaris hping does not work on the lo
+ a solaris problem, as stated in the tcpdump-workers mailing list,
+ so the libpcap can't do nothing to handle it properly.
+ .SH SEE ALSO
+-ping(8), traceroute(8), ifconfig(8), nmap(1)
+\ No newline at end of file
++ping(8), traceroute(8), ifconfig(8), nmap(1)
+--- a/docs/hping3.8
++++ b/docs/hping3.8
+@@ -352,7 +352,7 @@ options. If in doubt try
+ .I -N --id
+ Set ip->id field. Default id is random but if fragmentation is turned on
+ and id isn't specified it will be
+-.BR "getpid() & 0xFF" ,
++.BR "getpid() & 0xFFFF" ,
+ to implement a better solution is in TODO list.
+ .TP
+ .I -H --ipproto
+--- a/hping2.h
++++ b/hping2.h
+@@ -121,7 +121,7 @@
+ #define DEFAULT_ICMP_IP_IHL (IPHDR_SIZE >> 2)
+ #define DEFAULT_ICMP_IP_TOS 0
+ #define DEFAULT_ICMP_IP_TOT_LEN 0 /* computed by send_icmp_*() */
+-#define DEFAULT_ICMP_IP_ID 0 /* rand */
++#define DEFAULT_ICMP_IP_ID -1 /* rand */
+ #define DEFAULT_ICMP_CKSUM -1 /* -1 means compute the cksum */
+ #define DEFAULT_ICMP_IP_PROTOCOL 6 /* TCP */
+ #define DEFAULT_RAW_IP_PROTOCOL 6 /* TCP */
+--- a/parseoptions.c
++++ b/parseoptions.c
+@@ -468,6 +468,10 @@ int parse_options(int argc, char **argv)
+ break;
+ case OPT_ICMP_IPID:
+ icmp_ip_id = strtol(ago_optarg, NULL, 0);
++ if (icmp_ip_id < 0 || icmp_ip_id > 0xffff) {
++ fprintf(stderr, "Bad ICMP IP ID, resetting to random.\n");
++ icmp_ip_id = DEFAULT_ICMP_IP_ID;
++ }
+ break;
+ case OPT_ICMP_IPPROTO:
+ icmp_ip_protocol = strtol(ago_optarg, NULL, 0);
+--- a/sendicmp.c
++++ b/sendicmp.c
+@@ -83,7 +83,7 @@ void send_icmp_echo(void)
+ icmp->type = opt_icmptype; /* echo replay or echo request */
+ icmp->code = opt_icmpcode; /* should be indifferent */
+ icmp->checksum = 0;
+- icmp->un.echo.id = getpid() & 0xffff;
++ icmp->un.echo.id = icmp_ip_id == DEFAULT_ICMP_IP_ID ? getpid() & 0xffff : icmp_ip_id;
+ icmp->un.echo.sequence = _icmp_seq;
+
+ /* data */
--- /dev/null
+Subject: Off-by-one error with --dontfrag
+Author: Christian Mock <cm@coretec.at>
+Bugs-Debian: http://bugs.debian.org/537704
+Last-Update: 2009-09-04
+
+--- a/sendip_handler.c
++++ b/sendip_handler.c
+@@ -19,7 +19,7 @@ void send_ip_handler(char *packet, unsig
+ {
+ ip_optlen = ip_opt_build(ip_opt);
+
+- if (!opt_fragment && (size+ip_optlen+20 >= h_if_mtu))
++ if (!opt_fragment && (size+ip_optlen+20 > h_if_mtu))
+ {
+ /* auto-activate fragmentation */
+ virtual_mtu = h_if_mtu-20;
--- /dev/null
+Subject: Add RTT handling for ICMP destination unreachable packets.
+Author: Baruch Even <baruch@debian.org>
+Bug-Debian: http://bugs.debian.org/248273
+Last-Update: 2009-09-04
+
+--- a/waitpacket.c
++++ b/waitpacket.c
+@@ -229,6 +229,7 @@ int recv_icmp(void *packet, size_t size)
+ {
+ struct myicmphdr icmp;
+ struct myiphdr quoted_ip;
++ struct myudphdr quoted_udp;
+
+ /* Check if the packet can contain the ICMP header */
+ if (size < ICMPHDR_SIZE) {
+@@ -286,6 +287,18 @@ int recv_icmp(void *packet, size_t size)
+ case 3:
+ if (!opt_quiet)
+ log_icmp_unreach(inet_ntoa(src), icmp.code);
++ if (quoted_ip.protocol == IPPROTO_UDP)
++ {
++ int sequence = 0, status;
++ float ms_delay = 0.0;
++ unsigned short port;
++
++ /* Get RTT for UDP packet */
++ memcpy("ed_udp, packet+ICMPHDR_SIZE+(quoted_ip.ihl<<2), sizeof(quoted_udp));
++ port = ntohs(quoted_udp.uh_sport);
++ status = rtt(&sequence, port, &ms_delay);
++ printf("status=%d port=%d seq=%d\n", status, port, sequence);
++ }
+ return 1;
+ case 11:
+ if (opt_traceroute)
--- /dev/null
+Subject; Fix spelling error in binary (lintian -IE)
+Author: Romain Francoise <rfrancoise@debian.org>
+Last-Update: 2005-03-12
+
+--- a/parseoptions.c
++++ b/parseoptions.c
+@@ -179,7 +179,7 @@ void parse_route(unsigned char *route, u
+ str[j++] = '/';
+ break;
+ }
+- fprintf(stderr, "invalid IP adress in route\n");
++ fprintf(stderr, "invalid IP address in route\n");
+ fail_parse_route();
+ case ':':
+ if ((!i) && j && j < 4)
+--- a/getifname.c
++++ b/getifname.c
+@@ -206,7 +206,7 @@ int get_if_name(void)
+ printf("DEBUG: Output interface address: %s\n",
+ inet_ntoa(output_if_addr.sin_addr));
+ /* Put something in saved_ifname in order to tell
+- that the output adress is known */
++ that the output address is known */
+ saved_ifname[0] = 'X'; saved_ifname[1] = 0;
+ } else {
+ fprintf(stderr, "Warning: Unable to guess the output "
+--- a/usage.c
++++ b/usage.c
+@@ -50,7 +50,7 @@ void show_usage(void)
+ " -r --rel relativize id field (to estimate host traffic)\n"
+ " -f --frag split packets in more frag. (may pass weak acl)\n"
+ " -x --morefrag set more fragments flag\n"
+-" -y --dontfrag set dont fragment flag\n"
++" -y --dontfrag set don't fragment flag\n"
+ " -g --fragoff set the fragment offset\n"
+ " -m --mtu set virtual mtu, implies --frag if packet size > mtu\n"
+ " -o --tos type of service (default 0x00), try --tos help\n"
+@@ -131,8 +131,8 @@ void icmp_help(void)
+ "ICMP help:\n"
+ " ICMP concerned packet options:\n"
+ " --icmp-ipver set ip version ( default 4 )\n"
+-" --icmp-iphlen set ip header lenght ( default IPHDR_SIZE >> 2)\n"
+-" --icmp-iplen set ip total lengtht ( default real lenght )\n"
++" --icmp-iphlen set ip header length ( default IPHDR_SIZE >> 2)\n"
++" --icmp-iplen set ip total length ( default real length )\n"
+ " --icmp-ipid set ip id ( default random )\n"
+ " --icmp-ipproto set ip protocol ( default IPPROTO_TCP )\n"
+ " --icmp-ipsrc set ip source ( default 0.0.0.0 )\n"
+--- a/sendtcp.c
++++ b/sendtcp.c
+@@ -50,7 +50,7 @@ void send_tcp(void)
+ memcpy(&pseudoheader->saddr, &local.sin_addr.s_addr, 4);
+ memcpy(&pseudoheader->daddr, &remote.sin_addr.s_addr, 4);
+ pseudoheader->protocol = 6; /* tcp */
+- pseudoheader->lenght = htons(TCPHDR_SIZE+tcp_opt_size+data_size);
++ pseudoheader->length = htons(TCPHDR_SIZE+tcp_opt_size+data_size);
+
+ /* tcp header */
+ tcp->th_dport = htons(dst_port);
+--- a/sendudp.c
++++ b/sendudp.c
+@@ -46,7 +46,7 @@ void send_udp(void)
+ memcpy(&pseudoheader->saddr, &local.sin_addr.s_addr, 4);
+ memcpy(&pseudoheader->daddr, &remote.sin_addr.s_addr, 4);
+ pseudoheader->protocol = 17; /* udp */
+- pseudoheader->lenght = htons(packet_size);
++ pseudoheader->length = htons(packet_size);
+
+ /* udp header */
+ udp->uh_dport = htons(dst_port);
+--- a/sendicmp.c
++++ b/sendicmp.c
+@@ -243,7 +243,7 @@ void send_icmp_other(void)
+ memcpy(&pseudoheader->saddr, &icmp_ip_src.sin_addr.s_addr, 4);
+ memcpy(&pseudoheader->daddr, &icmp_ip_dst.sin_addr.s_addr, 4);
+ pseudoheader->protocol = icmp_ip.protocol;
+- pseudoheader->lenght = icmp_ip.tot_len;
++ pseudoheader->length = icmp_ip.tot_len;
+ icmp_udp->uh_sport = htons(icmp_ip_srcport);
+ icmp_udp->uh_dport = htons(icmp_ip_dstport);
+ icmp_udp->uh_ulen = htons(UDPHDR_SIZE + udp_data_len);
+--- a/hping2.h
++++ b/hping2.h
+@@ -138,7 +138,7 @@
+
+ /* fragmentation defines */
+ #define MF ((unsigned short)0x2000) /* more fragments */
+-#define DF ((unsigned short)0x4000) /* dont fragment */
++#define DF ((unsigned short)0x4000) /* don't fragment */
+ #define NF ((unsigned short)0x0000) /* no more fragments */
+
+ /* ip options defines */
+@@ -341,7 +341,7 @@ struct pseudohdr
+ __u32 daddr;
+ __u8 zero;
+ __u8 protocol;
+- __u16 lenght;
++ __u16 length;
+ };
+
+ #define PSEUDOHDR_SIZE sizeof(struct pseudohdr)
+--- a/ars.c
++++ b/ars.c
+@@ -698,7 +698,7 @@ int ars_udptcp_cksum(struct ars_packet *
+ memcpy(&pseudo.daddr, &ip->daddr, 4);
+ pseudo.protocol = (pkt->p_layer[layer].l_type == ARS_TYPE_TCP)
+ ? ARS_IPPROTO_TCP : ARS_IPPROTO_UDP;
+- pseudo.lenght = htons(ars_relative_size(pkt, layer));
++ pseudo.length = htons(ars_relative_size(pkt, layer));
+
+ /* Finally do the checksum */
+ ars_multi_cksum(&mc, ARS_MC_INIT, NULL, 0);
+--- a/datahandler.c
++++ b/datahandler.c
+@@ -26,7 +26,7 @@ void data_handler(char *data, int data_s
+ }
+
+ if (opt_sign) {
+- memcpy(data, sign, signlen); /* lenght pre-checked */
++ memcpy(data, sign, signlen); /* length pre-checked */
+ data+=signlen;
+ data_size-=signlen;
+ }
+--- a/ars.h
++++ b/ars.h
+@@ -67,7 +67,7 @@
+ #define ARS_MAX_IP_SIZE 65535
+
+ #define ARS_IP_MF ((unsigned short)0x2000) /* more fragments */
+-#define ARS_IP_DF ((unsigned short)0x4000) /* dont fragment */
++#define ARS_IP_DF ((unsigned short)0x4000) /* don't fragment */
+ #define ARS_IP_RF ((unsigned short)0x8000) /* reserved fragment flag */
+
+ #define ARS_IPOPT_COPY 0x80
+@@ -308,7 +308,7 @@ struct ars_pseudohdr
+ __u32 daddr;
+ __u8 zero;
+ __u8 protocol;
+- __u16 lenght;
++ __u16 length;
+ };
+
+ /* The IGRP header structure */
+--- a/sendip_handler.c
++++ b/sendip_handler.c
+@@ -35,7 +35,7 @@ void send_ip_handler(char *packet, unsig
+ unsigned short fragment_flag = 0;
+
+ if (opt_mf) fragment_flag |= MF; /* more fragments */
+- if (opt_df) fragment_flag |= DF; /* dont fragment */
++ if (opt_df) fragment_flag |= DF; /* don't fragment */
+ send_ip((char*)&local.sin_addr,
+ (char*)&remote.sin_addr,
+ packet, size, fragment_flag, ip_frag_offset,
--- /dev/null
+Subject: Fix incorrect data size check for UDP.
+Author: Luca Bigliardi <shammash@artha.org>
+Bug-Debian; http://bugs.debian.org/546590
+Last-Update: 2009-09-19
+
+--- a/parseoptions.c
++++ b/parseoptions.c
+@@ -606,9 +606,12 @@ int parse_options(int argc, char **argv)
+ if (opt_numeric == TRUE) opt_gethost = FALSE;
+
+ /* some error condition */
+- if (data_size+IPHDR_SIZE+TCPHDR_SIZE > 65535) {
++ if (data_size+IPHDR_SIZE+
++ (opt_udpmode?UDPHDR_SIZE:TCPHDR_SIZE) > 65535) {
+ printf("Option error: sorry, data size must be <= %lu\n",
+- (unsigned long)(65535-IPHDR_SIZE+TCPHDR_SIZE));
++ (unsigned long)(65535-(IPHDR_SIZE+
++ (opt_udpmode?UDPHDR_SIZE:TCPHDR_SIZE)))
++ );
+ exit(1);
+ }
+ else if (count <= 0 && count != -1) {
--- /dev/null
+Subject: Add tcp-mss support.
+Origin: http://cvsweb.netbsd.org/bsdweb.cgi/pkgsrc/net/hping/patches/
+Bug-Debian: http://bugs.debian.org/409391
+Last-Update: 2009-09-19
+
+--- a/main.c
++++ b/main.c
+@@ -44,7 +44,8 @@ unsigned int
+ signlen,
+ lsr_length = 0,
+ ssr_length = 0,
+- tcp_ack;
++ tcp_ack,
++ tcp_mss;
+
+
+ unsigned short int
+@@ -95,6 +96,7 @@ int
+ opt_tcpexitcode = FALSE,
+ opt_badcksum = FALSE,
+ opt_tr_keep_ttl = FALSE,
++ opt_tcp_mss = FALSE,
+ opt_tcp_timestamp = FALSE,
+ opt_clock_skew = FALSE,
+ cs_window = DEFAULT_CS_WINDOW,
+--- a/globals.h
++++ b/globals.h
+@@ -32,7 +32,8 @@ extern unsigned int
+ tcp_seqnum,
+ set_ack,
+ ip_header_length,
+- tcp_ack;
++ tcp_ack,
++ tcp_mss;
+
+ extern unsigned short int
+ data_size;
+@@ -77,6 +78,7 @@ extern int opt_debug,
+ opt_tcpexitcode,
+ opt_badcksum,
+ opt_tr_keep_ttl,
++ opt_tcp_mss,
+ opt_tcp_timestamp,
+ opt_clock_skew,
+ cs_window,
+--- a/parseoptions.c
++++ b/parseoptions.c
+@@ -31,7 +31,7 @@ enum { OPT_COUNT, OPT_INTERVAL, OPT_NUME
+ OPT_RROUTE, OPT_IPPROTO, OPT_ICMP_IPVER, OPT_ICMP_IPHLEN,
+ OPT_ICMP_IPLEN, OPT_ICMP_IPID, OPT_ICMP_IPPROTO, OPT_ICMP_CKSUM,
+ OPT_ICMP_TS, OPT_ICMP_ADDR, OPT_TCPEXITCODE, OPT_FAST, OPT_TR_KEEP_TTL,
+- OPT_TCP_TIMESTAMP, OPT_TR_STOP, OPT_TR_NO_RTT, OPT_ICMP_HELP,
++ OPT_TCP_TIMESTAMP, OPT_TCP_MSS, OPT_TR_STOP, OPT_TR_NO_RTT, OPT_ICMP_HELP,
+ OPT_RAND_DEST, OPT_RAND_SOURCE, OPT_LSRR, OPT_SSRR, OPT_ROUTE_HELP,
+ OPT_ICMP_IPSRC, OPT_ICMP_IPDST, OPT_ICMP_SRCPORT, OPT_ICMP_DSTPORT,
+ OPT_ICMP_GW, OPT_FORCE_ICMP, OPT_APD_SEND, OPT_SCAN, OPT_FASTER,
+@@ -125,6 +125,7 @@ static struct ago_optlist hping_optlist[
+ { '\0', "force-icmp", OPT_FORCE_ICMP, AGO_NOARG },
+ { '\0', "beep", OPT_BEEP, AGO_NOARG },
+ { '\0', "flood", OPT_FLOOD, AGO_NOARG },
++ { '\0', "tcp-mss", OPT_TCP_MSS, AGO_NEEDARG|AGO_EXCEPT0 },
+ { '\0', "clock-skew", OPT_CLOCK_SKEW, AGO_NOARG },
+ { '\0', "clock-skew-win", OPT_CS_WINDOW, AGO_NEEDARG},
+ { '\0', "clock-skew-win-shift", OPT_CS_WINDOW_SHIFT, AGO_NEEDARG},
+@@ -561,6 +562,10 @@ int parse_options(int argc, char **argv)
+ case OPT_FLOOD:
+ opt_flood = TRUE;
+ break;
++ case OPT_TCP_MSS:
++ opt_tcp_mss = TRUE;
++ tcp_mss = strtoul(ago_optarg, NULL, 0);
++ break;
+ case OPT_CLOCK_SKEW:
+ opt_tcp_timestamp = TRUE;
+ opt_clock_skew = TRUE;
+--- a/usage.c
++++ b/usage.c
+@@ -87,6 +87,7 @@ void show_usage(void)
+ " -X --xmas set X unused flag (0x40)\n"
+ " -Y --ymas set Y unused flag (0x80)\n"
+ " --tcpexitcode use last tcp->th_flags as exit code\n"
++" --tcp-mss enable the TCP MSS option with the given value\n"
+ " --tcp-timestamp enable the TCP timestamp option to guess the HZ/uptime\n"
+ "Clock skew detection\n"
+ " --clock-skew enable clock skew detection. Try with -S against open port\n"
+--- a/sendtcp.c
++++ b/sendtcp.c
+@@ -28,10 +28,12 @@ void send_tcp(void)
+ char *packet, *data;
+ struct mytcphdr *tcp;
+ struct pseudohdr *pseudoheader;
+- unsigned char *tstamp;
++ unsigned char *opts;
+
++ if (opt_tcp_mss)
++ tcp_opt_size += 4;
+ if (opt_tcp_timestamp)
+- tcp_opt_size = 12;
++ tcp_opt_size += 12;
+
+ packet_size = TCPHDR_SIZE + tcp_opt_size + data_size;
+ packet = malloc(PSEUDOHDR_SIZE + packet_size);
+@@ -41,7 +43,7 @@ void send_tcp(void)
+ }
+ pseudoheader = (struct pseudohdr*) packet;
+ tcp = (struct mytcphdr*) (packet+PSEUDOHDR_SIZE);
+- tstamp = (unsigned char*) (packet+PSEUDOHDR_SIZE+TCPHDR_SIZE);
++ opts = (unsigned char*) (packet+PSEUDOHDR_SIZE+TCPHDR_SIZE);
+ data = (char*) (packet+PSEUDOHDR_SIZE+TCPHDR_SIZE+tcp_opt_size);
+
+ memset(packet, 0, PSEUDOHDR_SIZE+packet_size);
+@@ -64,14 +66,24 @@ void send_tcp(void)
+ tcp->th_win = htons(src_winsize);
+ tcp->th_flags = tcp_th_flags;
+
++ /* tcp MSS option */
++ if (opt_tcp_mss) {
++ opts[0] = 2;
++ opts[1] = 4; /* 4 bytes, kind+len+MSS */
++ opts[2] = tcp_mss >> 8;
++ opts[3] = tcp_mss & 0xff;
++ opts += 4;
++ }
++
+ /* tcp timestamp option */
+ if (opt_tcp_timestamp) {
+ __u32 randts = rand() ^ (rand() << 16);
+- tstamp[0] = tstamp[1] = 1; /* NOOP */
+- tstamp[2] = 8;
+- tstamp[3] = 10; /* 10 bytes, kind+len+T1+T2 */
+- memcpy(tstamp+4, &randts, 4); /* random */
+- memset(tstamp+8, 0, 4); /* zero */
++ opts[0] = opts[1] = 1; /* NOOP */
++ opts[2] = 8;
++ opts[3] = 10; /* 10 bytes, kind+len+T1+T2 */
++ memcpy(opts+4, &randts, 4); /* random */
++ memset(opts+8, 0, 4); /* zero */
++ opts += 12;
+ }
+
+ /* data */
+--- a/docs/hping3.8
++++ b/docs/hping3.8
+@@ -98,6 +98,8 @@ hping2 \- send (almost) arbitrary TCP/IP
+ ] [
+ .B \-\-tcpexitcode
+ ] [
++.B \-\-tcp-mss
++] [
+ .B \-\-tcp-timestamp
+ ] [
+ .B \-\-tr-stop
+@@ -510,6 +512,9 @@ numbers are predictable.
+ .I -b --badcksum
+ Send packets with a bad UDP/TCP checksum.
+ .TP
++.I --tcp-mss
++Enable the TCP MSS option and set it to the given value.
++.TP
+ .I --tcp-timestamp
+ Enable the TCP timestamp option, and try to guess the timestamp update
+ frequency and the remote system uptime.
+--- a/docs/french/hping2-fr.8
++++ b/docs/french/hping2-fr.8
+@@ -99,6 +99,8 @@ hping2 \- envoie des paquets TCP/IP (pre
+ ] [
+ .B \-\-tcpexitcode
+ ] [
++.B \-\-tcp-mss
++] [
+ .B \-\-tcp-timestamp
+ ] [
+ .B \-\-tr-stop
+@@ -538,6 +540,9 @@ pouvez le voir les numéros de séquence d
+ .I -b --badcksum
+ Envoie des paquets avec une mauvaise somme de contrôle UDP/TCP
+ .TP
++.I --tcp-mss
++Active l'option TCP MSS et la fixe avec la valeur donnée.
++.TP
+ .I --tcp-timestamp
+ Active l'option TCP timestamp, et essaye de deviner la fréquence de mise à
+ jour du timestamp et l'uptime du système distant.
--- /dev/null
+Author: Michael Tautschnig <mt@debian.org>
+Subject: Conflicting types for variable ip_optlen
+ - globals.h: extern char ip_optlen;
+ - main.c: unsigned ip_optlen;
+ Undefined behaviour if the value of ip_optlen exceeds 127 for
+ any architecture with signed char type.
+Bug-Debian: https://bugs.debian.org/688458
+
+--- a/main.c
++++ b/main.c
+@@ -156,7 +156,7 @@ unsigned char
+ lsr [255] = {0},
+ ssr [255] = {0};
+
+-unsigned
++char
+ ip_optlen = 0;
+
+ struct sockaddr_in
--- /dev/null
+Description: Fixes declaration of global variable
+Author: Marcio de Souza Oliveira <marciosouza@debian.org>
+Last-Update: 2020-09-02
+--- a/hping2.h
++++ b/hping2.h
+@@ -357,7 +357,7 @@ struct delaytable_element {
+ int status;
+ };
+
+-volatile struct delaytable_element delaytable[TABLESIZE];
++extern volatile struct delaytable_element delaytable[TABLESIZE];
+
+ /* protos */
+ void nop(void); /* nop */
--- /dev/null
+Description: Fixes replies when icmp-ipid is used
+Author: David Eisner <deisner@gmail.com>
+Last-Update: 2015-12-18
+--- a/waitpacket.c
++++ b/waitpacket.c
+@@ -244,7 +244,8 @@ int recv_icmp(void *packet, size_t size)
+ if ((icmp.type == ICMP_ECHOREPLY ||
+ icmp.type == ICMP_TIMESTAMPREPLY ||
+ icmp.type == ICMP_ADDRESSREPLY) &&
+- icmp.un.echo.id == (getpid() & 0xffff))
++ icmp.un.echo.id == ((icmp_ip_id == DEFAULT_ICMP_IP_ID) ?
++ getpid() & 0xffff : icmp_ip_id) )
+ {
+ int icmp_seq = icmp.un.echo.sequence;
+ int status;
--- /dev/null
+--- a/getifname.c
++++ b/getifname.c
+@@ -59,7 +59,7 @@ int get_if_name(void)
+ known_output_if = 1;
+ if (opt_debug)
+ printf("DEBUG: Output interface address: %s\n",
+- inet_ntoa(sa.sin_addr));
++ inet_ntoa(output_if_addr.sin_addr));
+ } else {
+ fprintf(stderr, "Warning: Unable to guess the output "
+ "interface\n");