From 91618a14260faadc7bea7db256e6ebaf05d731dd Mon Sep 17 00:00:00 2001 From: Alarig Le Lay Date: Sat, 14 Nov 2020 22:35:32 +0100 Subject: [PATCH] net-analyzer/mtr: Upstream issue 232 Package-Manager: Portage-3.0.8, Repoman-3.0.2 Signed-off-by: Alarig Le Lay --- net-analyzer/mtr/Manifest | 1 + net-analyzer/mtr/files/mtr-0.88-tinfo.patch | 13 + .../mtr/files/mtr-0.94-ipv4-sockets.patch | 387 ++++++++++++++++++ net-analyzer/mtr/metadata.xml | 12 + net-analyzer/mtr/mtr-0.94-r1.ebuild | 62 +++ 5 files changed, 475 insertions(+) create mode 100644 net-analyzer/mtr/Manifest create mode 100644 net-analyzer/mtr/files/mtr-0.88-tinfo.patch create mode 100644 net-analyzer/mtr/files/mtr-0.94-ipv4-sockets.patch create mode 100644 net-analyzer/mtr/metadata.xml create mode 100644 net-analyzer/mtr/mtr-0.94-r1.ebuild diff --git a/net-analyzer/mtr/Manifest b/net-analyzer/mtr/Manifest new file mode 100644 index 0000000..69472ac --- /dev/null +++ b/net-analyzer/mtr/Manifest @@ -0,0 +1 @@ +DIST mtr-0.94.tar.gz 143616 BLAKE2B e9b4619a85a515d729f0987d5882fb91e4bfa3be82476efbfdb832d0b13ed334be1c1a1bcf8ab4ca820002e79ca4a24d0b50f2739d9284b7dec0b8852a1a91e0 SHA512 0e58bd79562ff80f9308135562ab22aa1f1eea686aefd3aef07bac05e661e34b60fde7c66c96bf4f0919f546376fbd6106ecd8fa92328c24f6f903097496bf11 diff --git a/net-analyzer/mtr/files/mtr-0.88-tinfo.patch b/net-analyzer/mtr/files/mtr-0.88-tinfo.patch new file mode 100644 index 0000000..c7252b7 --- /dev/null +++ b/net-analyzer/mtr/files/mtr-0.88-tinfo.patch @@ -0,0 +1,13 @@ +--- a/configure.ac ++++ b/configure.ac +@@ -101,7 +101,10 @@ + # (On Solaris 11.3, ncurses builds and links for us, but curses does not.) + [AC_SEARCH_LIBS( + [initscr], [ncurses curses], ++ [AC_SEARCH_LIBS( ++ [raw], [ncurses curses cursesX tinfo], + [AC_DEFINE([HAVE_CURSES], [1], [Define if a curses library available])], ++ [with_ncurses=no])], + [with_ncurses=no]) + ]) + AM_CONDITIONAL([WITH_CURSES], [test "x$with_ncurses" = xyes]) diff --git a/net-analyzer/mtr/files/mtr-0.94-ipv4-sockets.patch b/net-analyzer/mtr/files/mtr-0.94-ipv4-sockets.patch new file mode 100644 index 0000000..3d92201 --- /dev/null +++ b/net-analyzer/mtr/files/mtr-0.94-ipv4-sockets.patch @@ -0,0 +1,387 @@ +diff --git a/packet/construct_unix.c b/packet/construct_unix.c +index dff17d8..3d72b10 100644 +--- a/packet/construct_unix.c ++++ b/packet/construct_unix.c +@@ -71,19 +71,6 @@ uint16_t compute_checksum( + return (~sum & 0xffff); + } + +-/* Encode the IP header length field in the order required by the OS. */ +-static +-uint16_t length_byte_swap( +- const struct net_state_t *net_state, +- uint16_t length) +-{ +- if (net_state->platform.ip_length_host_order) { +- return length; +- } else { +- return htons(length); +- } +-} +- + /* Construct a combined sockaddr from a source address and source port */ + static + void construct_addr_port( +@@ -95,38 +82,9 @@ void construct_addr_port( + *sockaddr_port_offset(addr_with_port) = htons(port); + } + +-/* Construct a header for IP version 4 */ +-static +-void construct_ip4_header( +- const struct net_state_t *net_state, +- const struct probe_t *probe, +- char *packet_buffer, +- int packet_size, +- const struct probe_param_t *param) +-{ +- struct IPHeader *ip; +- +- ip = (struct IPHeader *) &packet_buffer[0]; +- +- memset(ip, 0, sizeof(struct IPHeader)); +- +- ip->version = 0x45; +- ip->tos = param->type_of_service; +- ip->len = length_byte_swap(net_state, packet_size); +- ip->ttl = param->ttl; +- ip->protocol = param->protocol; +-// ip->id = htons(getpid()); +- memcpy(&ip->saddr, +- sockaddr_addr_offset(&probe->local_addr), +- sockaddr_addr_size(&probe->local_addr)); +- memcpy(&ip->daddr, +- sockaddr_addr_offset(&probe->remote_addr), +- sockaddr_addr_size(&probe->remote_addr)); +-} +- + /* Construct an ICMP header for IPv4 */ + static +-void construct_icmp4_header( ++int construct_icmp4_packet( + const struct net_state_t *net_state, + struct probe_t *probe, + char *packet_buffer, +@@ -134,22 +92,17 @@ void construct_icmp4_header( + const struct probe_param_t *param) + { + struct ICMPHeader *icmp; +- int icmp_size; + +- if (net_state->platform.ip4_socket_raw) { +- icmp = (struct ICMPHeader *) &packet_buffer[sizeof(struct IPHeader)]; +- icmp_size = packet_size - sizeof(struct IPHeader); +- } else { +- icmp = (struct ICMPHeader *) &packet_buffer[0]; +- icmp_size = packet_size; +- } ++ icmp = (struct ICMPHeader *) packet_buffer; + + memset(icmp, 0, sizeof(struct ICMPHeader)); + + icmp->type = ICMP_ECHO; + icmp->id = htons(getpid()); + icmp->sequence = htons(probe->sequence); +- icmp->checksum = htons(compute_checksum(icmp, icmp_size)); ++ icmp->checksum = htons(compute_checksum(icmp, packet_size)); ++ ++ return 0; + } + + /* Construct an ICMP header for IPv6 */ +@@ -238,7 +191,7 @@ int udp4_checksum(void *pheader, void *udata, int psize, int dsize, + with the probe. + */ + static +-void construct_udp4_header( ++int construct_udp4_packet( + const struct net_state_t *net_state, + struct probe_t *probe, + char *packet_buffer, +@@ -248,13 +201,8 @@ void construct_udp4_header( + struct UDPHeader *udp; + int udp_size; + +- if (net_state->platform.ip4_socket_raw) { +- udp = (struct UDPHeader *) &packet_buffer[sizeof(struct IPHeader)]; +- udp_size = packet_size - sizeof(struct IPHeader); +- } else { +- udp = (struct UDPHeader *) &packet_buffer[0]; +- udp_size = packet_size; +- } ++ udp = (struct UDPHeader *) packet_buffer; ++ udp_size = packet_size; + + memset(udp, 0, sizeof(struct UDPHeader)); + +@@ -283,6 +231,8 @@ void construct_udp4_header( + *checksum_off = htons(udp4_checksum(&udph, udp, + sizeof(struct UDPPseudoHeader), + udp_size, udp->checksum != 0)); ++ ++ return 0; + } + + /* Construct a header for UDPv6 probes */ +@@ -545,10 +495,10 @@ int construct_ip4_packet( + int packet_size, + const struct probe_param_t *param) + { +- int send_socket = net_state->platform.ip4_send_socket; ++ int send_socket; + bool is_stream_protocol = false; +- int tos, ttl, socket; +- bool bind_send_socket = false; ++ int tos, ttl; ++ bool bind_send_socket = true; + struct sockaddr_storage current_sockaddr; + int current_sockaddr_len; + +@@ -558,23 +508,34 @@ int construct_ip4_packet( + } else if (param->protocol == IPPROTO_SCTP) { + is_stream_protocol = true; + #endif +- } else { ++ } else if (param->protocol == IPPROTO_ICMP) { + if (net_state->platform.ip4_socket_raw) { +- construct_ip4_header(net_state, probe, packet_buffer, packet_size, +- param); ++ send_socket = net_state->platform.icmp4_send_socket; ++ } else { ++ send_socket = net_state->platform.ip4_txrx_icmp_socket; + } +- if (param->protocol == IPPROTO_ICMP) { +- construct_icmp4_header(net_state, probe, packet_buffer, +- packet_size, param); +- } else if (param->protocol == IPPROTO_UDP) { +- construct_udp4_header(net_state, probe, packet_buffer, +- packet_size, param); ++ ++ if (construct_icmp4_packet ++ (net_state, probe, packet_buffer, packet_size, param)) { ++ return -1; ++ } ++ } else if (param->protocol == IPPROTO_UDP) { ++ if (net_state->platform.ip4_socket_raw) { ++ send_socket = net_state->platform.udp4_send_socket; + } else { +- errno = EINVAL; ++ send_socket = net_state->platform.ip4_txrx_udp_socket; ++ } ++ ++ if (construct_udp4_packet ++ (net_state, probe, packet_buffer, packet_size, param)) { + return -1; + } ++ } else { ++ errno = EINVAL; ++ return -1; + } + ++ + if (is_stream_protocol) { + send_socket = + open_stream_socket(net_state, param->protocol, probe->sequence, +@@ -608,54 +569,51 @@ int construct_ip4_packet( + #endif + + /* +- Bind src port when not using raw socket to pass in ICMP id, kernel +- get ICMP id from src_port when using DGRAM socket. ++ Check the current socket address, and if it is the same ++ as the source address we intend, we will skip the bind. ++ This is to accommodate Solaris, which, as of Solaris 11.3, ++ will return an EINVAL error on bind if the socket is already ++ bound, even if the same address is used. + */ +- if (!net_state->platform.ip4_socket_raw && +- param->protocol == IPPROTO_ICMP && +- !param->is_probing_byte_order) { +- current_sockaddr_len = sizeof(struct sockaddr_in); +- bind_send_socket = true; +- socket = net_state->platform.ip4_txrx_icmp_socket; +- if (getsockname(socket, (struct sockaddr *) ¤t_sockaddr, +- ¤t_sockaddr_len)) { +- return -1; +- } +- struct sockaddr_in *sin_cur = +- (struct sockaddr_in *) ¤t_sockaddr; ++ current_sockaddr_len = sizeof(struct sockaddr_in); ++ if (getsockname(send_socket, (struct sockaddr *) ¤t_sockaddr, ++ ¤t_sockaddr_len) == 0) { ++ struct sockaddr_in *sin_cur = (struct sockaddr_in *) ¤t_sockaddr; + +- /* avoid double bind */ +- if (sin_cur->sin_port) { +- bind_send_socket = false; ++ if (net_state->platform.ip4_socket_raw) { ++ if (memcmp(¤t_sockaddr, ++ &probe->local_addr, sizeof(struct sockaddr_in)) == 0) { ++ bind_send_socket = false; ++ } ++ } else { ++ /* avoid double bind for DGRAM socket */ ++ if (sin_cur->sin_port) { ++ bind_send_socket = false; ++ } + } + } + + /* Bind to our local address */ +- if (bind_send_socket && bind(socket, (struct sockaddr *)&probe->local_addr, ++ if (bind_send_socket && bind(send_socket, (struct sockaddr *)&probe->local_addr, + sizeof(struct sockaddr_in))) { + return -1; + } + +- /* set TOS and TTL for non-raw socket */ +- if (!net_state->platform.ip4_socket_raw && !param->is_probing_byte_order) { +- if (param->protocol == IPPROTO_ICMP) { +- socket = net_state->platform.ip4_txrx_icmp_socket; +- } else if (param->protocol == IPPROTO_UDP) { +- socket = net_state->platform.ip4_txrx_udp_socket; +- } else { +- return 0; +- } +- tos = param->type_of_service; +- if (setsockopt(socket, SOL_IP, IP_TOS, &tos, sizeof(int))) { +- return -1; +- } +- ttl = param->ttl; +- if (setsockopt(socket, SOL_IP, IP_TTL, +- &ttl, sizeof(int)) == -1) { +- return -1; +- } ++ /* Set the type of service */ ++ tos = param->type_of_service; ++ if (setsockopt(send_socket, SOL_IP, IP_TOS, &tos, sizeof(int))) { ++ return -1; + } + ++ /* Set the time-to-live */ ++ ttl = param->ttl; ++ if (setsockopt(send_socket, SOL_IP, IP_TTL, ++ &ttl, sizeof(int)) == -1) { ++ return -1; ++ } ++ ++ ++ + return 0; + } + +diff --git a/packet/probe_unix.c b/packet/probe_unix.c +index e77e46f..3be1f55 100644 +--- a/packet/probe_unix.c ++++ b/packet/probe_unix.c +@@ -87,16 +87,21 @@ int send_packet( + } else if (sockaddr->ss_family == AF_INET) { + sockaddr_length = sizeof(struct sockaddr_in); + +- if (net_state->platform.ip4_socket_raw) { +- send_socket = net_state->platform.ip4_send_socket; +- } else { +- if (param->protocol == IPPROTO_ICMP) { +- if (param->is_probing_byte_order) { +- send_socket = net_state->platform.ip4_tmp_icmp_socket;; +- } else { +- send_socket = net_state->platform.ip4_txrx_icmp_socket; +- } +- } else if (param->protocol == IPPROTO_UDP) { ++ if (param->protocol == IPPROTO_ICMP) { ++ if (net_state->platform.ip4_socket_raw) { ++ send_socket = net_state->platform.icmp4_send_socket; ++ } else { ++ send_socket = net_state->platform.ip4_txrx_icmp_socket; ++ } ++ } else if (param->protocol == IPPROTO_UDP) { ++ if (net_state->platform.ip4_socket_raw) { ++ send_socket = net_state->platform.udp4_send_socket; ++ /* we got a ipv4 udp raw socket ++ * the remote port is in the payload ++ * we do not set in the sockaddr ++ */ ++ *sockaddr_port_offset(&dst) = 0; ++ } else { + send_socket = net_state->platform.ip4_txrx_udp_socket; + if (param->dest_port) { + *sockaddr_port_offset(&dst) = htons(param->dest_port); +@@ -105,6 +110,7 @@ int send_packet( + } + } + } ++ + } + + if (send_socket == 0) { +@@ -236,26 +242,19 @@ static + int open_ip4_sockets_raw( + struct net_state_t *net_state) + { +- int send_socket; ++ int send_socket_icmp; ++ int send_socket_udp; + int recv_socket; +- int trueopt = 1; + +- send_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); +- if (send_socket == -1) { +- send_socket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); +- if (send_socket == -1) { +- return -1; +- } ++ send_socket_icmp = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); ++ if (send_socket_icmp == -1) { ++ return -1; + } + +- /* +- We will be including the IP header in transmitted packets. +- Linux doesn't require this, but BSD derived network stacks do. +- */ +- if (setsockopt +- (send_socket, IPPROTO_IP, IP_HDRINCL, &trueopt, sizeof(int))) { ++ send_socket_udp = socket(AF_INET, SOCK_RAW, IPPROTO_UDP); ++ if (send_socket_udp == -1) { ++ close(send_socket_icmp); + +- close(send_socket); + return -1; + } + +@@ -265,13 +264,15 @@ int open_ip4_sockets_raw( + */ + recv_socket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + if (recv_socket == -1) { +- close(send_socket); ++ close(send_socket_icmp); ++ close(send_socket_udp); + return -1; + } + + net_state->platform.ip4_present = true; + net_state->platform.ip4_socket_raw = true; +- net_state->platform.ip4_send_socket = send_socket; ++ net_state->platform.icmp4_send_socket = send_socket_icmp; ++ net_state->platform.udp4_send_socket = send_socket_udp; + net_state->platform.ip4_recv_socket = recv_socket; + + return 0; +diff --git a/packet/probe_unix.h b/packet/probe_unix.h +index 0ce7657..c6309e6 100644 +--- a/packet/probe_unix.h ++++ b/packet/probe_unix.h +@@ -54,8 +54,11 @@ struct net_state_platform_t { + /* true if ipv6 socket is raw socket */ + bool ip6_socket_raw; + +- /* Socket used to send raw IPv4 packets */ +- int ip4_send_socket; ++ /* Send socket for ICMPv6 packets */ ++ int icmp4_send_socket; ++ ++ /* Send socket for UDPv6 packets */ ++ int udp4_send_socket; + + /* Socket used to receive IPv4 ICMP replies */ + int ip4_recv_socket; diff --git a/net-analyzer/mtr/metadata.xml b/net-analyzer/mtr/metadata.xml new file mode 100644 index 0000000..632c6e6 --- /dev/null +++ b/net-analyzer/mtr/metadata.xml @@ -0,0 +1,12 @@ + + + + +netmon@gentoo.org +Gentoo network monitoring and analysis project + + +Disable support for IP address lookups +Enable JSON output support through dev-libs/jansson + + diff --git a/net-analyzer/mtr/mtr-0.94-r1.ebuild b/net-analyzer/mtr/mtr-0.94-r1.ebuild new file mode 100644 index 0000000..5ef64fa --- /dev/null +++ b/net-analyzer/mtr/mtr-0.94-r1.ebuild @@ -0,0 +1,62 @@ +# Copyright 1999-2020 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=7 +inherit autotools bash-completion-r1 fcaps + +DESCRIPTION="My TraceRoute, an Excellent network diagnostic tool" +HOMEPAGE="https://www.bitwizard.nl/mtr/" +SRC_URI="https://github.com/traviscross/${PN}/archive/v${PV}.tar.gz -> ${P}.tar.gz" + +LICENSE="GPL-2" +SLOT="0" +KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86 ~amd64-linux ~x86-linux ~ppc-macos ~x64-macos ~x86-macos" +IUSE="gtk +ipinfo +ipv6 jansson ncurses" + +RDEPEND=" + gtk? ( + dev-libs/glib:2 + x11-libs/gtk+:3 + ) + jansson? ( dev-libs/jansson ) + ncurses? ( sys-libs/ncurses:0= ) +" +DEPEND=" + ${RDEPEND} +" +BDEPEND=" + virtual/pkgconfig +" +DOCS=( AUTHORS FORMATS NEWS README.md SECURITY TODO ) +FILECAPS=( cap_net_raw usr/sbin/mtr-packet ) +PATCHES=( + "${FILESDIR}/${PN}-0.88-tinfo.patch" + "${FILESDIR}/${P}-ipv4-sockets.patch" +) +RESTRICT="test" + +src_prepare() { + default + + eautoreconf +} + +src_configure() { + econf \ + $(use_enable ipv6) \ + $(use_with gtk) \ + $(use_with ipinfo) \ + $(use_with jansson) \ + $(use_with ncurses) \ + --with-bashcompletiondir="$(get_bashcompdir)" +} + +pkg_postinst() { + fcaps_pkg_postinst + + if use prefix && [[ ${CHOST} == *-darwin* ]] ; then + ewarn "mtr needs root privileges to run. To grant them:" + ewarn " % sudo chown root ${EPREFIX}/usr/sbin/mtr" + ewarn " % sudo chmod u+s ${EPREFIX}/usr/sbin/mtr" + fi +}