From d4e362502ae85baf3b8eac67035e1b9d7bc2b94f Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 26 Jun 2020 21:24:33 +0200 Subject: [PATCH] Add MPTCP patch to net-tools --- net-tools/Makefile | 74 ++++++ net-tools/patches/mptcp-support.patch | 338 ++++++++++++++++++++++++++ 2 files changed, 412 insertions(+) create mode 100644 net-tools/Makefile create mode 100644 net-tools/patches/mptcp-support.patch diff --git a/net-tools/Makefile b/net-tools/Makefile new file mode 100644 index 000000000..6336c57e5 --- /dev/null +++ b/net-tools/Makefile @@ -0,0 +1,74 @@ +# +# Copyright (C) 2006-2010 OpenWrt.org +# Copyright (C) 2016 Stijn Segers +# Copyright (C) 2020 Ycarus (Yannick Chabanois) for OpenMPTCProuter +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=net-tools +PKG_SOURCE_DATE:=2018-11-03 +PKG_SOURCE_VERSION:=0eebece8c964e3cfa8a018f42b2e7e751a7009a0 +PKG_RELEASE:=2 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://git.code.sf.net/p/net-tools/code +PKG_MIRROR_HASH:=9d978b9f8ccae4af623a299155c62d9b3d31213182c785f925bf8704d48a04c9 + +PKG_MAINTAINER:=Yannick Chabanois +PKG_LICENSE:=GPL-2.0-or-later +PKG_LICENSE_FILES:=COPYING + +include $(INCLUDE_DIR)/package.mk + +define Package/mii-tool + SECTION:=net + CATEGORY:=Network + TITLE:=configure media type using MII commands + URL:=http://net-tools.sourceforge.net/ +endef + +define Package/mii-tool/description + The mii-tool command allows you to set or autodetect the media type + or mii chipset-based ethernet devices. It traditionally had been + distributed in the net-tools package. This is a single distribution + optimized for embedded systems and fully automated cross/-sysroot-builds +endef + +define Package/net-tools-route + SECTION:=net + CATEGORY:=Network + TITLE:=net-tools - route utility + URL:=http://net-tools.sourceforge.net/ + PROVIDES:=route + ALTERNATIVES:=300:/sbin/route:/usr/libexec/net-tools-route +endef + +define Package/net-tools-route/description + Replace busybox version of the route command with the full net-tools + version. This is normally not needed as busybox is smaller and provides + sufficient functionality, but some users may want or need the full + functionality of the net-tools variant (e.g. AF_X25). +endef + +define Build/Configure + # Failed configure.sh leaves stub config.h around. + rm -f $(PKG_BUILD_DIR)/config.h + ( cd $(PKG_BUILD_DIR); yes $$$$'\n' | ./configure.sh config.in ) +endef + +define Package/mii-tool/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/mii-tool $(1)/usr/sbin/ +endef + +define Package/net-tools-route/install + $(INSTALL_DIR) $(1)/usr/libexec + $(INSTALL_BIN) $(PKG_BUILD_DIR)/route $(1)/usr/libexec/net-tools-route +endef + +$(eval $(call BuildPackage,mii-tool)) +$(eval $(call BuildPackage,net-tools-route)) diff --git a/net-tools/patches/mptcp-support.patch b/net-tools/patches/mptcp-support.patch new file mode 100644 index 000000000..b9f69d0f8 --- /dev/null +++ b/net-tools/patches/mptcp-support.patch @@ -0,0 +1,338 @@ +diff -aurN net-tools-code-0eebece8c964e3cfa8a018f42b2e7e751a7009a0/lib/pathnames.h net-tools-mptcp_v0.95/lib/pathnames.h +--- net-tools-code-0eebece8c964e3cfa8a018f42b2e7e751a7009a0/lib/pathnames.h 2018-11-03 14:23:32.000000000 +0100 ++++ net-tools-mptcp_v0.95/lib/pathnames.h 2019-06-22 22:52:42.000000000 +0200 +@@ -14,6 +14,7 @@ + #define _PATH_PROCNET_IGMP6 "/proc/net/igmp6" + #define _PATH_PROCNET_TCP "/proc/net/tcp" + #define _PATH_PROCNET_TCP6 "/proc/net/tcp6" ++#define _PATH_PROCNET_MPTCP "/proc/net/mptcp_net/mptcp" + #define _PATH_PROCNET_UDP "/proc/net/udp" + #define _PATH_PROCNET_UDP6 "/proc/net/udp6" + #define _PATH_PROCNET_UDPLITE "/proc/net/udplite" +diff -aurN net-tools-code-0eebece8c964e3cfa8a018f42b2e7e751a7009a0/netstat.c net-tools-mptcp_v0.95/netstat.c +--- net-tools-code-0eebece8c964e3cfa8a018f42b2e7e751a7009a0/netstat.c 2018-11-03 14:23:32.000000000 +0100 ++++ net-tools-mptcp_v0.95/netstat.c 2019-06-22 22:52:42.000000000 +0200 +@@ -115,7 +115,7 @@ + #endif + + /* prototypes for statistics.c */ +-void parsesnmp(int, int, int, int); ++void parsesnmp(int, int, int, int, int); + void parsesnmp6(int, int, int); + + typedef enum { +@@ -155,6 +155,7 @@ + int flag_opt = 0; + int flag_raw = 0; + int flag_tcp = 0; ++int flag_mptcp = 0; + int flag_sctp= 0; + int flag_udp = 0; + int flag_udplite = 0; +@@ -1206,6 +1207,83 @@ + tcp_do_one, "tcp", "tcp6"); + } + ++static void mptcp_do_one(int lnr, const char *line, const char *prot) ++{ ++ int d, ipv6, num, local_port, rem_port, state, nsub; ++ unsigned long txq, rxq, local_token, remote_token, inode; ++ char rem_addr[128], local_addr[128]; ++ struct sockaddr_storage localsas, remsas; ++ struct sockaddr_in *localaddr = (struct sockaddr_in *)&localsas; ++ struct sockaddr_in *remaddr = (struct sockaddr_in *)&remsas; ++ const struct aftype *ap; ++#if HAVE_AFINET6 ++ char addr6[INET6_ADDRSTRLEN]; ++ struct in6_addr in6; ++ extern struct aftype inet6_aftype; ++#endif ++ ++ if (lnr == 0) ++ return; ++ ++ num = sscanf(line, "%d: %lX %lX %d %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X " ++ "%X %X %lX:%lX %lu\n", &d, &local_token, &remote_token, ++ &ipv6, local_addr, &local_port, rem_addr, &rem_port, ++ &state, &nsub, &txq, &rxq, &inode); ++ ++ if (strlen(local_addr) > 8) { ++#if HAVE_AFINET6 ++ /* Demangle what the kernel gives us */ ++ sscanf(local_addr, "%08X%08X%08X%08X", ++ &in6.s6_addr32[0], &in6.s6_addr32[1], ++ &in6.s6_addr32[2], &in6.s6_addr32[3]); ++ inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6)); ++ inet6_aftype.input(1, addr6, &localsas); ++ sscanf(rem_addr, "%08X%08X%08X%08X", ++ &in6.s6_addr32[0], &in6.s6_addr32[1], ++ &in6.s6_addr32[2], &in6.s6_addr32[3]); ++ inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6)); ++ inet6_aftype.input(1, addr6, &remsas); ++ localsas.ss_family = AF_INET6; ++ remsas.ss_family = AF_INET6; ++#endif ++ } else { ++ sscanf(local_addr, "%X", ++ &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr); ++ sscanf(rem_addr, "%X", ++ &((struct sockaddr_in *) &remaddr)->sin_addr.s_addr); ++ localsas.ss_family = AF_INET; ++ remsas.ss_family = AF_INET; ++ } ++ ++ if (num < 12) { ++ fprintf(stderr, _("warning, got bogus mptcp line.\n")); ++ return; ++ } ++ ++ if ((ap = get_afntype(localsas.ss_family)) == NULL) { ++ fprintf(stderr, _("netstat: unsupported address family %d !\n"), ++ localsas.ss_family); ++ return; ++ } ++ ++ addr_do_one(local_addr, sizeof(local_addr), 22, ap, &localsas, local_port, "tcp"); ++ addr_do_one(rem_addr, sizeof(rem_addr), 22, ap, &remsas, rem_port, "tcp"); ++ ++ printf("%-4s %6ld %6ld %-*s %-*s %-11s", ++ prot, rxq, txq, (int)netmax(23,strlen(local_addr)), local_addr, ++ (int)netmax(23,strlen(rem_addr)), rem_addr, _(tcp_state[state])); ++ ++ if (flag_mptcp) ++ printf(" %-11lu %-12lu", local_token, remote_token); ++ ++ finish_this_one(0, inode, NULL); ++} ++ ++static int mptcp_info(void) ++{ ++ INFO_GUTS(_PATH_PROCNET_MPTCP, "AF INET (mptcp)", mptcp_do_one, "mptcp"); ++} ++ + static int notnull(const struct sockaddr_storage *sas) + { + const struct sockaddr_in *sin = (const struct sockaddr_in *)sas; +@@ -1994,7 +2072,7 @@ + fprintf(fp, _(" -Z, --context display SELinux security context for sockets\n")); + #endif + +- fprintf(fp, _("\n ={-t|--tcp} {-u|--udp} {-U|--udplite} {-S|--sctp} {-w|--raw}\n")); ++ fprintf(fp, _("\n ={-t|--tcp} {-m|--mptcp} {-u|--udp} {-U|--udplite} {-S|--sctp} {-w|--raw}\n")); + fprintf(fp, _(" {-x|--unix} --ax25 --ipx --netrom\n")); + fprintf(fp, _(" =Use '-6|-4' or '-A ' or '--'; default: %s\n"), DFLT_AF); + fprintf(fp, _(" List of possible address families (which support routing):\n")); +@@ -2019,6 +2097,7 @@ + #endif + {"protocol", 1, 0, 'A'}, + {"tcp", 0, 0, 't'}, ++ {"mptcp", 0, 0, 'm'}, + {"sctp", 0, 0, 'S'}, + {"udp", 0, 0, 'u'}, + {"udplite", 0, 0, 'U'}, +@@ -2055,7 +2134,7 @@ + getroute_init(); /* Set up AF routing support */ + + afname[0] = '\0'; +- while ((i = getopt_long(argc, argv, "A:CFMacdeghilnNoprsStuUvVWw2fx64?Z", longopts, &lop)) != EOF) ++ while ((i = getopt_long(argc, argv, "A:CFMacdeghilnNoprsStmuUvVWw2fx64?Z", longopts, &lop)) != EOF) + switch (i) { + case -1: + break; +@@ -2146,6 +2225,9 @@ + case 't': + flag_tcp++; + break; ++ case 'm': ++ flag_mptcp++; ++ break; + case 'S': + flag_sctp++; + break; +@@ -2194,17 +2276,17 @@ + usage(E_OPTERR); + + if ((flag_inet || flag_inet6 || flag_sta) && +- !(flag_tcp || flag_sctp || flag_udp || flag_udplite || flag_raw)) +- flag_noprot = flag_tcp = flag_sctp = flag_udp = flag_udplite = flag_raw = 1; ++ !(flag_tcp || flag_sctp || flag_mptcp || flag_udp || flag_udplite || flag_raw)) ++ flag_noprot = flag_tcp = flag_mptcp = flag_sctp = flag_udp = flag_udplite = flag_raw = 1; + +- if ((flag_tcp || flag_sctp || flag_udp || flag_udplite || flag_raw || flag_igmp) && ++ if ((flag_tcp || flag_sctp || flag_mptcp || flag_udp || flag_udplite || flag_raw || flag_igmp) && + !(flag_inet || flag_inet6)) + flag_inet = flag_inet6 = 1; + + if (flag_bluetooth && !(flag_l2cap || flag_rfcomm)) + flag_l2cap = flag_rfcomm = 1; + +- flag_arg = flag_tcp + flag_sctp + flag_udplite + flag_udp + flag_raw + flag_unx ++ flag_arg = flag_tcp + flag_mptcp +flag_sctp + flag_udplite + flag_udp + flag_raw + flag_unx + + flag_ipx + flag_ax25 + flag_netrom + flag_igmp + flag_x25 + flag_rose + + flag_l2cap + flag_rfcomm; + +@@ -2234,7 +2316,7 @@ + + if (!strcmp(afname, "inet")) { + #if HAVE_AFINET +- parsesnmp(flag_raw, flag_tcp, flag_udp, flag_sctp); ++ parsesnmp(flag_raw, flag_tcp, flag_udp, flag_sctp, flag_mptcp); + #else + ENOSUPP("netstat", "AF INET"); + #endif +@@ -2284,7 +2366,7 @@ + return (i); + } + for (;;) { +- if (!flag_arg || flag_tcp || flag_sctp || flag_udp || flag_udplite || flag_raw) { ++ if (!flag_arg || flag_tcp || flag_mptcp || flag_sctp || flag_udp || flag_udplite || flag_raw) { + #if HAVE_AFINET + prg_cache_load(); + printf(_("Active Internet connections ")); /* xxx */ +@@ -2298,6 +2380,8 @@ + printf(_("(w/o servers)")); + } + printf(_("\nProto Recv-Q Send-Q Local Address Foreign Address State ")); /* xxx */ ++ if (flag_mptcp) ++ printf(_(" Local Token Remote Token ")); + if (flag_exp > 1) + printf(_(" User Inode ")); + print_progname_banner(); +@@ -2318,6 +2402,12 @@ + if (i) + return (i); + } ++ ++ if (!flag_arg || flag_mptcp) { ++ i = mptcp_info(); ++ if (i) ++ return (i); ++ } + + if (!flag_arg || flag_sctp) { + i = sctp_info(); +diff -aurN net-tools-code-0eebece8c964e3cfa8a018f42b2e7e751a7009a0/statistics.c net-tools-mptcp_v0.95/statistics.c +--- net-tools-code-0eebece8c964e3cfa8a018f42b2e7e751a7009a0/statistics.c 2018-11-03 14:23:32.000000000 +0100 ++++ net-tools-mptcp_v0.95/statistics.c 2019-06-22 22:52:42.000000000 +0200 +@@ -13,7 +13,7 @@ + #include "intl.h" + #include "proc.h" + +-static int print_static,f_raw,f_tcp,f_udp,f_sctp,f_unknown = 1; ++static int print_static,f_raw,f_tcp,f_udp,f_sctp,f_mptcp,f_unknown = 1; + + enum State { + number = 0, opt_number, i_forward, i_inp_icmp, i_outp_icmp, i_rto_alg, +@@ -295,6 +295,51 @@ + {"SctpShutdowns", N_("%llu Number of Graceful Terminations"), number}, + }; + ++static const struct entry Mptcptab[] = ++{ /* Keep the entries sorted! */ ++ {"AddAddrRx", N_("%llu Number of ADD_ADDRs received"), number}, ++ {"AddAddrTx", N_("%llu Number of ADD_ADDRs sent"), number}, ++ {"DSSNoMatchTCP", N_("%llu Number of DSS-mapping/TCP sequence number mismatches"), number}, ++ {"DSSNotMatching", N_("%llu Number of new mismatched mappings"), number}, ++ {"DSSPurgeOldSubSegs", N_("%llu Number of skbs removed from the rcv-queue due to missing DSS-mapping"), number}, ++ {"DSSSplitTail", N_("%llu Number of trimmed segments at the tail"), number}, ++ {"DSSTrimHead", N_("%llu Number of trimmed segments at the head"), number}, ++ {"InfiniteMapRx", N_("%llu Number of infinite mappings received"), number}, ++ {"MPCapableACKRX", N_("%llu Number of received third ACKs with MP_CAPABLE"), number}, ++ {"MPCapableFallbackACK", N_("%llu Number of server-side fallbacks during the 3-way handshake"), number}, ++ {"MPCapableFallbackSYNACK", N_("%llu Number of client-side fallbacks during the 3-way handshake"), number}, ++ {"MPCapableRetransFallback", N_("%llu Number of times the client-side stopped sending MP_CAPABLE after too many SYN-retransmissions"), ++ number}, ++ {"MPCapableSYNACKRX", N_("%llu Number of received SYN/ACKs with MP_CAPABLE"), number}, ++ {"MPCapableSYNRX", N_("%llu Number of received SYNs with MP_CAPABLE"), number}, ++ {"MPCapableSYNTX", N_("%llu Number of sent SYNs with MP_CAPABLE"), number}, ++ {"MPCsumFail", N_("%llu Number of received segments with an invalid checksum"), number}, ++ {"MPFailRX", N_("%llu Number of MP_FAILs received"), number}, ++ {"MPFallbackAckInit", N_("%llu Number of fallbacks upon ack without data-ack on initial subflow"), number}, ++ {"MPFallbackAckSub", N_("%llu Number of fallbacks upon ack without data-ack on new subflow"), number}, ++ {"MPFallbackDataInit", N_("%llu Number of fallbacks upon data without DSS at the beginning on initial subflow"), number}, ++ {"MPFallbackDataSub", N_("%llu Number of fallbacks upon data without DSS at the beginning on new subflow"), number}, ++ {"MPFastcloseRX", N_("%llu Number of FAST_CLOSEs received"), number}, ++ {"MPFastcloseTX", N_("%llu Number of FAST_CLOSEs sent"), number}, ++ {"MPJoinAckHMacFailure", N_("%llu Number of HMAC mismatches on ACK + MP_JOIN"), number}, ++ {"MPJoinAckMissing", N_("%llu Number of third ACKs on a new subflow not containing a MP_JOIN"), number}, ++ {"MPJoinAckRTO", N_("%llu Number of retransmission timeouts for third ACK + MP_JOIN"), number}, ++ {"MPJoinAckRexmit", N_("%llu Number of retransmitted ACK + MP_JOINs"), number}, ++ {"MPJoinAckRx", N_("%llu Number of ACK + MP_JOINs received"), number}, ++ {"MPJoinAlreadyFallenback", N_("%llu Number of received MP_JOINs on a session that has fallen back to reg. TCP"), number}, ++ {"MPJoinNoTokenFound", N_("%llu Number of received MP_JOINs without a token"), number}, ++ {"MPJoinSynAckHMacFailure", N_("%llu Number of received SYN/ACK + MP_JOINs with a HMAC mismatch"), number}, ++ {"MPJoinSynAckRx", N_("%llu Number of SYN/ACK + MP_JOINs received"), number}, ++ {"MPJoinSynRx", N_("%llu Number of SYN + MP_JOINs received"), number}, ++ {"MPJoinSynTx", N_("%llu Number of SYN + MP_JOINs sent"), number}, ++ {"MPRemoveAddrSubDelete", N_("%llu Number of subflows removed due to REMOVE_ADDR"), number}, ++ {"MPTCPCsumEnabled", N_("%llu Number of MPTCP connections created with DSS-checksum enabled"), number}, ++ {"MPTCPRetrans", N_("%llu Number of segments retransmitted at the MPTCP level"), number}, ++ {"NoDSSInWindow", N_("%llu Number of too many packets received without a DSS option errors"), number}, ++ {"RemAddrRx", N_("%llu Number of REMOVE_ADDRs received"), number}, ++ {"RemAddrTx", N_("%llu Number of REMOVE_ADDRs sent"), number}, ++}; ++ + struct tabtab { + const char *title; + const struct entry *tab; +@@ -310,6 +355,7 @@ + {"Udp", Udptab, sizeof(Udptab), &f_udp}, + {"Sctp", Sctptab, sizeof(Sctptab), &f_sctp}, + {"TcpExt", Tcpexttab, sizeof(Tcpexttab), &f_tcp}, ++ {"Mptcp", Mptcptab, sizeof(Mptcptab), &f_mptcp}, + {NULL} + }; + +@@ -503,13 +549,13 @@ + } + + /* Process a file with name-value lines (like /proc/net/sctp/snmp) */ +-static void process_fd2(FILE *f, const char *filename) ++static void process_fd2(FILE *f, const char *filename, const char *tablename) + { + char buf1[1024]; + char *sp; + const struct tabtab *tab; + +- tab = newtable(snmptabs, "Sctp"); ++ tab = newtable(snmptabs, tablename); + + while (fgets(buf1, sizeof buf1, f)) { + sp = buf1 + strcspn(buf1, " \t\n"); +@@ -527,11 +573,11 @@ + } + } + +-void parsesnmp(int flag_raw, int flag_tcp, int flag_udp, int flag_sctp) ++void parsesnmp(int flag_raw, int flag_tcp, int flag_udp, int flag_sctp, int flag_mptcp) + { + FILE *f; + +- f_raw = flag_raw; f_tcp = flag_tcp; f_udp = flag_udp; f_sctp = flag_sctp; ++ f_raw = flag_raw; f_tcp = flag_tcp; f_udp = flag_udp; f_sctp = flag_sctp; f_mptcp = flag_mptcp; + + f = proc_fopen("/proc/net/snmp"); + if (!f) { +@@ -561,12 +607,21 @@ + + f = proc_fopen("/proc/net/sctp/snmp"); + if (f) { +- process_fd2(f,"/proc/net/sctp/snmp"); ++ process_fd2(f,"/proc/net/sctp/snmp", "Sctp"); + if (ferror(f)) { + perror("/proc/net/sctp/snmp"); + fclose(f); + } + } ++ ++ f = proc_fopen("/proc/net/mptcp_net/snmp"); ++ if (f) { ++ process_fd2(f,"/proc/net/mptcp_net/snmp", "Mptcp"); ++ if (ferror(f)) { ++ perror("/proc/net/mptcp_net/snmp"); ++ fclose(f); ++ } ++ } + } + + void parsesnmp6(int flag_raw, int flag_tcp, int flag_udp)