crux-musl

Unnamed repository; edit this file 'description' to name the repository.
git clone https://codeberg.org/emmett1/crux-musl
Log | Files | Refs | README | LICENSE

0016-ping-make-ping-work-without-root-privileges.patch (6389B)


      1 From 19c6c34fb6318605e58a9b209cf742d559c0d467 Mon Sep 17 00:00:00 2001
      2 From: Natanael Copa <ncopa@alpinelinux.org>
      3 Date: Tue, 29 Mar 2016 09:23:08 +0200
      4 Subject: [PATCH] ping: make ping work without root privileges
      5 MIME-Version: 1.0
      6 Content-Type: text/plain; charset=UTF-8
      7 Content-Transfer-Encoding: 8bit
      8 
      9 ---
     10  networking/ping.c | 115 +++++++++++++++++++++++++++++++++++++---------
     11  1 file changed, 94 insertions(+), 21 deletions(-)
     12 
     13 diff --git a/networking/ping.c b/networking/ping.c
     14 index 9805695a1..5e4488abd 100644
     15 --- a/networking/ping.c
     16 +++ b/networking/ping.c
     17 @@ -208,6 +208,7 @@ enum {
     18  	pingsock = 0,
     19  };
     20  
     21 +static int using_dgram;
     22  static void
     23  #if ENABLE_PING6
     24  create_icmp_socket(len_and_sockaddr *lsa)
     25 @@ -224,9 +225,23 @@ create_icmp_socket(void)
     26  #endif
     27  		sock = socket(AF_INET, SOCK_RAW, 1); /* 1 == ICMP */
     28  	if (sock < 0) {
     29 -		if (errno == EPERM)
     30 -			bb_simple_error_msg_and_die(bb_msg_perm_denied_are_you_root);
     31 -		bb_simple_perror_msg_and_die(bb_msg_can_not_create_raw_socket);
     32 +		if (errno != EPERM)
     33 +			bb_simple_perror_msg_and_die(bb_msg_can_not_create_raw_socket);
     34 +#if defined(__linux__) || defined(__APPLE__)
     35 +		/* We don't have root privileges.  Try SOCK_DGRAM instead.
     36 +		 * Linux needs net.ipv4.ping_group_range for this to work.
     37 +		 * MacOSX allows ICMP_ECHO, ICMP_TSTAMP or ICMP_MASKREQ
     38 +		 */
     39 +#if ENABLE_PING6
     40 +		if (lsa->u.sa.sa_family == AF_INET6)
     41 +			sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6);
     42 +		else
     43 +#endif
     44 +			sock = socket(AF_INET, SOCK_DGRAM, 1); /* 1 == ICMP */
     45 +		if (sock < 0)
     46 +#endif
     47 +		bb_simple_error_msg_and_die(bb_msg_perm_denied_are_you_root);
     48 +		using_dgram = 1;
     49  	}
     50  
     51  	xmove_fd(sock, pingsock);
     52 @@ -279,10 +294,12 @@ static void ping4(len_and_sockaddr *lsa)
     53  				bb_simple_perror_msg("recvfrom");
     54  			continue;
     55  		}
     56 -		if (c >= 76) {			/* ip + icmp */
     57 -			struct iphdr *iphdr = (struct iphdr *) G.packet;
     58 +		if (c >= 76 || using_dgram && (c == 64)) {			/* ip + icmp */
     59 +			if(!using_dgram) {
     60 +				struct iphdr *iphdr = (struct iphdr *) G.packet;
     61  
     62 -			pkt = (struct icmp *) (G.packet + (iphdr->ihl << 2));	/* skip ip hdr */
     63 +				pkt = (struct icmp *) (G.packet + (iphdr->ihl << 2));	/* skip ip hdr */
     64 +			} else pkt = (struct icmp *) G.packet;
     65  			if (pkt->icmp_id != G.myid)
     66  				continue; /* not our ping */
     67  			if (pkt->icmp_type == ICMP_ECHOREPLY)
     68 @@ -691,19 +708,21 @@ static void unpack_tail(int sz, uint32_t *tp,
     69  }
     70  static int unpack4(char *buf, int sz, struct sockaddr_in *from)
     71  {
     72 -	struct icmp *icmppkt;
     73  	struct iphdr *iphdr;
     74 +	struct icmp *icmppkt;
     75  	int hlen;
     76  
     77  	/* discard if too short */
     78  	if (sz < (datalen + ICMP_MINLEN))
     79  		return 0;
     80 +	if(!using_dgram) {
     81 +		/* check IP header */
     82 +		iphdr = (struct iphdr *) buf;
     83 +		hlen = iphdr->ihl << 2;
     84 +		sz -= hlen;
     85 +		icmppkt = (struct icmp *) (buf + hlen);
     86 +	} else icmppkt = (struct icmp *) buf;
     87  
     88 -	/* check IP header */
     89 -	iphdr = (struct iphdr *) buf;
     90 -	hlen = iphdr->ihl << 2;
     91 -	sz -= hlen;
     92 -	icmppkt = (struct icmp *) (buf + hlen);
     93  	if (icmppkt->icmp_id != myid)
     94  		return 0;				/* not our ping */
     95  
     96 @@ -715,7 +734,7 @@ static int unpack4(char *buf, int sz, struct sockaddr_in *from)
     97  			tp = (uint32_t *) icmppkt->icmp_data;
     98  		unpack_tail(sz, tp,
     99  			inet_ntoa(*(struct in_addr *) &from->sin_addr.s_addr),
    100 -			recv_seq, iphdr->ttl);
    101 +			recv_seq, using_dgram ? 42 : iphdr->ttl);
    102  		return 1;
    103  	}
    104  	if (icmppkt->icmp_type != ICMP_ECHO) {
    105 @@ -765,11 +784,31 @@ static void ping4(len_and_sockaddr *lsa)
    106  	int sockopt;
    107  
    108  	pingaddr.sin = lsa->u.sin;
    109 -	if (source_lsa) {
    110 +	if (source_lsa && !using_dgram) {
    111  		if (setsockopt(pingsock, IPPROTO_IP, IP_MULTICAST_IF,
    112  				&source_lsa->u.sa, source_lsa->len))
    113  			bb_simple_error_msg_and_die("can't set multicast source interface");
    114  		xbind(pingsock, &source_lsa->u.sa, source_lsa->len);
    115 +	} else if(using_dgram) {
    116 +		struct sockaddr_in sa;
    117 +		socklen_t sl;
    118 +
    119 +		sa.sin_family = AF_INET;
    120 +		sa.sin_port = 0;
    121 +		sa.sin_addr.s_addr = source_lsa ?
    122 +			source_lsa->u.sin.sin_addr.s_addr : 0;
    123 +		sl = sizeof(sa);
    124 +
    125 +		if (bind(pingsock, (struct sockaddr *) &sa, sl) == -1) {
    126 +			perror("bind");
    127 +			exit(2);
    128 +		}
    129 +
    130 +		if (getsockname(pingsock, (struct sockaddr *) &sa, &sl) == -1) {
    131 +			perror("getsockname");
    132 +			exit(2);
    133 +		}
    134 +		myid = sa.sin_port;
    135  	}
    136  
    137  	/* enable broadcast pings */
    138 @@ -786,6 +825,15 @@ static void ping4(len_and_sockaddr *lsa)
    139  		setsockopt_int(pingsock, IPPROTO_IP, IP_MULTICAST_TTL, opt_ttl);
    140  	}
    141  
    142 +	if(using_dgram) {
    143 +		int hold = 65536;
    144 +		if (setsockopt(pingsock, SOL_IP, IP_RECVTTL, (char *)&hold, sizeof(hold)))
    145 +			perror("WARNING: setsockopt(IP_RECVTTL)");
    146 +		if (setsockopt(pingsock, SOL_IP, IP_RETOPTS, (char *)&hold, sizeof(hold)))
    147 +			perror("WARNING: setsockopt(IP_RETOPTS)");
    148 +
    149 +	}
    150 +
    151  	signal(SIGINT, print_stats_and_exit);
    152  
    153  	/* start the ping's going ... */
    154 @@ -823,10 +871,33 @@ static void ping6(len_and_sockaddr *lsa)
    155  	char control_buf[CMSG_SPACE(36)];
    156  
    157  	pingaddr.sin6 = lsa->u.sin6;
    158 -	if (source_lsa)
    159 +	if (source_lsa && !using_dgram)
    160  		xbind(pingsock, &source_lsa->u.sa, source_lsa->len);
    161 +	else if(using_dgram) {
    162 +		struct sockaddr_in6 sa = {0};
    163 +		socklen_t sl;
    164 +
    165 +		sa.sin6_family = AF_INET6;
    166 +		sa.sin6_port = 0;
    167 +		if(source_lsa) {
    168 +			memcpy(&sa.sin6_addr, &source_lsa->u.sin6.sin6_addr, sizeof(struct in6_addr));
    169 +		}
    170 +		sl = sizeof(sa);
    171 +
    172 +		if (bind(pingsock, (struct sockaddr *) &sa, sl) == -1) {
    173 +			perror("bind");
    174 +			exit(2);
    175 +		}
    176 +
    177 +		if (getsockname(pingsock, (struct sockaddr *) &sa, &sl) == -1) {
    178 +			perror("getsockname");
    179 +			exit(2);
    180 +		}
    181 +		myid = sa.sin6_port;
    182 +	}
    183  
    184  #ifdef ICMP6_FILTER
    185 +	if(!using_dgram)
    186  	{
    187  		struct icmp6_filter filt;
    188  		if (!(option_mask32 & OPT_VERBOSE)) {
    189 @@ -972,12 +1043,14 @@ static int common_ping_main(int opt, char **argv)
    190  		interval = INT_MAX/1000000;
    191  	G.interval_us = interval * 1000000;
    192  
    193 -	myid = (uint16_t) getpid();
    194 -	/* we can use native-endian ident, but other Unix ping/traceroute
    195 -	 * utils use *big-endian pid*, and e.g. traceroute on our machine may be
    196 -	 * *not* from busybox, idents may collide. Follow the convention:
    197 -	 */
    198 -	myid = htons(myid);
    199 +	if (!using_dgram) {
    200 +		myid = (uint16_t) getpid();
    201 +		/* we can use native-endian ident, but other Unix ping/traceroute
    202 +		 * utils use *big-endian pid*, and e.g. traceroute on our machine may be
    203 +		 * *not* from busybox, idents may collide. Follow the convention:
    204 +		 */
    205 +		myid = htons(myid);
    206 +	}
    207  	hostname = argv[optind];
    208  #if ENABLE_PING6
    209  	{