summaryrefslogtreecommitdiff
path: root/aports/busybox/0006-ping-make-ping-work-without-root-privileges.patch
diff options
context:
space:
mode:
Diffstat (limited to 'aports/busybox/0006-ping-make-ping-work-without-root-privileges.patch')
-rw-r--r--aports/busybox/0006-ping-make-ping-work-without-root-privileges.patch206
1 files changed, 206 insertions, 0 deletions
diff --git a/aports/busybox/0006-ping-make-ping-work-without-root-privileges.patch b/aports/busybox/0006-ping-make-ping-work-without-root-privileges.patch
new file mode 100644
index 0000000..ed35229
--- /dev/null
+++ b/aports/busybox/0006-ping-make-ping-work-without-root-privileges.patch
@@ -0,0 +1,206 @@
+From 278c73292f2cfc1ecef2dac71efdc7201c021211 Mon Sep 17 00:00:00 2001
+From: Natanael Copa <ncopa@alpinelinux.org>
+Date: Tue, 29 Mar 2016 18:59:22 +0200
+Subject: [PATCH] ping: make ping work without root privileges
+
+---
+ networking/ping.c | 115 +++++++++++++++++++++++++++++++++++++---------
+ 1 file changed, 94 insertions(+), 21 deletions(-)
+
+diff --git a/networking/ping.c b/networking/ping.c
+index c4a15e06e..a2dccb57f 100644
+--- a/networking/ping.c
++++ b/networking/ping.c
+@@ -170,6 +170,7 @@ enum {
+ pingsock = 0,
+ };
+
++static int using_dgram;
+ static void
+ #if ENABLE_PING6
+ create_icmp_socket(len_and_sockaddr *lsa)
+@@ -186,9 +187,23 @@ create_icmp_socket(void)
+ #endif
+ sock = socket(AF_INET, SOCK_RAW, 1); /* 1 == ICMP */
+ if (sock < 0) {
+- if (errno == EPERM)
+- bb_simple_error_msg_and_die(bb_msg_perm_denied_are_you_root);
+- bb_simple_perror_msg_and_die(bb_msg_can_not_create_raw_socket);
++ if (errno != EPERM)
++ bb_simple_perror_msg_and_die(bb_msg_can_not_create_raw_socket);
++#if defined(__linux__) || defined(__APPLE__)
++ /* We don't have root privileges. Try SOCK_DGRAM instead.
++ * Linux needs net.ipv4.ping_group_range for this to work.
++ * MacOSX allows ICMP_ECHO, ICMP_TSTAMP or ICMP_MASKREQ
++ */
++#if ENABLE_PING6
++ if (lsa->u.sa.sa_family == AF_INET6)
++ sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6);
++ else
++#endif
++ sock = socket(AF_INET, SOCK_DGRAM, 1); /* 1 == ICMP */
++ if (sock < 0)
++#endif
++ bb_simple_error_msg_and_die(bb_msg_perm_denied_are_you_root);
++ using_dgram = 1;
+ }
+
+ xmove_fd(sock, pingsock);
+@@ -241,10 +256,12 @@ static void ping4(len_and_sockaddr *lsa)
+ bb_simple_perror_msg("recvfrom");
+ continue;
+ }
+- if (c >= 76) { /* ip + icmp */
+- struct iphdr *iphdr = (struct iphdr *) G.packet;
++ if (c >= 76 || using_dgram && (c == 64)) { /* ip + icmp */
++ if(!using_dgram) {
++ struct iphdr *iphdr = (struct iphdr *) G.packet;
+
+- pkt = (struct icmp *) (G.packet + (iphdr->ihl << 2)); /* skip ip hdr */
++ pkt = (struct icmp *) (G.packet + (iphdr->ihl << 2)); /* skip ip hdr */
++ } else pkt = (struct icmp *) G.packet;
+ if (pkt->icmp_id != G.myid)
+ continue; /* not our ping */
+ if (pkt->icmp_type == ICMP_ECHOREPLY)
+@@ -653,19 +670,21 @@ static void unpack_tail(int sz, uint32_t *tp,
+ }
+ static int unpack4(char *buf, int sz, struct sockaddr_in *from)
+ {
+- struct icmp *icmppkt;
+ struct iphdr *iphdr;
++ struct icmp *icmppkt;
+ int hlen;
+
+ /* discard if too short */
+ if (sz < (datalen + ICMP_MINLEN))
+ return 0;
++ if(!using_dgram) {
++ /* check IP header */
++ iphdr = (struct iphdr *) buf;
++ hlen = iphdr->ihl << 2;
++ sz -= hlen;
++ icmppkt = (struct icmp *) (buf + hlen);
++ } else icmppkt = (struct icmp *) buf;
+
+- /* check IP header */
+- iphdr = (struct iphdr *) buf;
+- hlen = iphdr->ihl << 2;
+- sz -= hlen;
+- icmppkt = (struct icmp *) (buf + hlen);
+ if (icmppkt->icmp_id != myid)
+ return 0; /* not our ping */
+
+@@ -677,7 +696,7 @@ static int unpack4(char *buf, int sz, struct sockaddr_in *from)
+ tp = (uint32_t *) icmppkt->icmp_data;
+ unpack_tail(sz, tp,
+ inet_ntoa(*(struct in_addr *) &from->sin_addr.s_addr),
+- recv_seq, iphdr->ttl);
++ recv_seq, using_dgram ? 42 : iphdr->ttl);
+ return 1;
+ }
+ if (icmppkt->icmp_type != ICMP_ECHO) {
+@@ -727,11 +746,31 @@ static void ping4(len_and_sockaddr *lsa)
+ int sockopt;
+
+ pingaddr.sin = lsa->u.sin;
+- if (source_lsa) {
++ if (source_lsa && !using_dgram) {
+ if (setsockopt(pingsock, IPPROTO_IP, IP_MULTICAST_IF,
+ &source_lsa->u.sa, source_lsa->len))
+ bb_simple_error_msg_and_die("can't set multicast source interface");
+ xbind(pingsock, &source_lsa->u.sa, source_lsa->len);
++ } else if(using_dgram) {
++ struct sockaddr_in sa;
++ socklen_t sl;
++
++ sa.sin_family = AF_INET;
++ sa.sin_port = 0;
++ sa.sin_addr.s_addr = source_lsa ?
++ source_lsa->u.sin.sin_addr.s_addr : 0;
++ sl = sizeof(sa);
++
++ if (bind(pingsock, (struct sockaddr *) &sa, sl) == -1) {
++ perror("bind");
++ exit(2);
++ }
++
++ if (getsockname(pingsock, (struct sockaddr *) &sa, &sl) == -1) {
++ perror("getsockname");
++ exit(2);
++ }
++ myid = sa.sin_port;
+ }
+
+ /* enable broadcast pings */
+@@ -748,6 +787,15 @@ static void ping4(len_and_sockaddr *lsa)
+ setsockopt_int(pingsock, IPPROTO_IP, IP_MULTICAST_TTL, opt_ttl);
+ }
+
++ if(using_dgram) {
++ int hold = 65536;
++ if (setsockopt(pingsock, SOL_IP, IP_RECVTTL, (char *)&hold, sizeof(hold)))
++ perror("WARNING: setsockopt(IP_RECVTTL)");
++ if (setsockopt(pingsock, SOL_IP, IP_RETOPTS, (char *)&hold, sizeof(hold)))
++ perror("WARNING: setsockopt(IP_RETOPTS)");
++
++ }
++
+ signal(SIGINT, print_stats_and_exit);
+
+ /* start the ping's going ... */
+@@ -785,10 +833,33 @@ static void ping6(len_and_sockaddr *lsa)
+ char control_buf[CMSG_SPACE(36)];
+
+ pingaddr.sin6 = lsa->u.sin6;
+- if (source_lsa)
++ if (source_lsa && !using_dgram)
+ xbind(pingsock, &source_lsa->u.sa, source_lsa->len);
++ else if(using_dgram) {
++ struct sockaddr_in6 sa = {0};
++ socklen_t sl;
++
++ sa.sin6_family = AF_INET6;
++ sa.sin6_port = 0;
++ if(source_lsa) {
++ memcpy(&sa.sin6_addr, &source_lsa->u.sin6.sin6_addr, sizeof(struct in6_addr));
++ }
++ sl = sizeof(sa);
++
++ if (bind(pingsock, (struct sockaddr *) &sa, sl) == -1) {
++ perror("bind");
++ exit(2);
++ }
++
++ if (getsockname(pingsock, (struct sockaddr *) &sa, &sl) == -1) {
++ perror("getsockname");
++ exit(2);
++ }
++ myid = sa.sin6_port;
++ }
+
+ #ifdef ICMP6_FILTER
++ if(!using_dgram)
+ {
+ struct icmp6_filter filt;
+ if (!(option_mask32 & OPT_VERBOSE)) {
+@@ -934,12 +1005,14 @@ static int common_ping_main(int opt, char **argv)
+ interval = INT_MAX/1000000;
+ G.interval_us = interval * 1000000;
+
+- myid = (uint16_t) getpid();
+- /* we can use native-endian ident, but other Unix ping/traceroute
+- * utils use *big-endian pid*, and e.g. traceroute on our machine may be
+- * *not* from busybox, idents may collide. Follow the convention:
+- */
+- myid = htons(myid);
++ if (!using_dgram) {
++ myid = (uint16_t) getpid();
++ /* we can use native-endian ident, but other Unix ping/traceroute
++ * utils use *big-endian pid*, and e.g. traceroute on our machine may be
++ * *not* from busybox, idents may collide. Follow the convention:
++ */
++ myid = htons(myid);
++ }
+ hostname = argv[optind];
+ #if ENABLE_PING6
+ {