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)