dnsd: fix a number of bugs. Ideas by Ming-Ching Tiew (mctiew AT yahoo.com)
[oweals/busybox.git] / networking / arping.c
index 2b7a43cb63a9df9ecea40e3e4dfbbe8fd1a65139..915af326187525fd0f1b25e9cb229779ca060887 100644 (file)
@@ -61,10 +61,16 @@ struct globals {
 #define received   (G.received  )
 #define brd_recv   (G.brd_recv  )
 #define req_recv   (G.req_recv  )
-#define INIT_G() \
-       do { \
-               count = -1; \
-       } while (0)
+#define INIT_G() do { \
+       count = -1; \
+} while (0)
+
+// If GNUisms are not available...
+//static void *mempcpy(void *_dst, const void *_src, int n)
+//{
+//     memcpy(_dst, _src, n);
+//     return (char*)_dst + n;
+//}
 
 static int send_pack(struct in_addr *src_addr,
                        struct in_addr *dst_addr, struct sockaddr_ll *ME,
@@ -81,20 +87,15 @@ static int send_pack(struct in_addr *src_addr,
        ah->ar_pln = 4;
        ah->ar_op = option_mask32 & ADVERT ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST);
 
-       memcpy(p, &ME->sll_addr, ah->ar_hln);
-       p += ME->sll_halen;
-
-       memcpy(p, src_addr, 4);
-       p += 4;
+       p = mempcpy(p, &ME->sll_addr, ah->ar_hln);
+       p = mempcpy(p, src_addr, 4);
 
        if (option_mask32 & ADVERT)
-               memcpy(p, &ME->sll_addr, ah->ar_hln);
+               p = mempcpy(p, &ME->sll_addr, ah->ar_hln);
        else
-               memcpy(p, &HE->sll_addr, ah->ar_hln);
-       p += ah->ar_hln;
+               p = mempcpy(p, &HE->sll_addr, ah->ar_hln);
 
-       memcpy(p, dst_addr, 4);
-       p += 4;
+       p = mempcpy(p, dst_addr, 4);
 
        err = sendto(sock_fd, buf, p - buf, 0, (struct sockaddr *) HE, sizeof(*HE));
        if (err == p - buf) {
@@ -106,7 +107,7 @@ static int send_pack(struct in_addr *src_addr,
        return err;
 }
 
-static void finish(void) ATTRIBUTE_NORETURN;
+static void finish(void) NORETURN;
 static void finish(void)
 {
        if (!(option_mask32 & QUIET)) {
@@ -152,6 +153,15 @@ static bool recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
        struct arphdr *ah = (struct arphdr *) buf;
        unsigned char *p = (unsigned char *) (ah + 1);
        struct in_addr src_ip, dst_ip;
+       /* moves below assume in_addr is 4 bytes big, ensure that */
+       struct BUG_in_addr_must_be_4 {
+               char BUG_in_addr_must_be_4[
+                       sizeof(struct in_addr) == 4 ? 1 : -1
+               ];
+               char BUG_s_addr_must_be_4[
+                       sizeof(src_ip.s_addr) == 4 ? 1 : -1
+               ];
+       };
 
        /* Filter out wild packets */
        if (FROM->sll_pkttype != PACKET_HOST
@@ -170,13 +180,13 @@ static bool recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
 
        /* Protocol must be IP. */
        if (ah->ar_pro != htons(ETH_P_IP)
-               || (ah->ar_pln != 4)
-               || (ah->ar_hln != me.sll_halen)
-               || (len < sizeof(*ah) + 2 * (4 + ah->ar_hln)))
+        || (ah->ar_pln != 4)
+        || (ah->ar_hln != me.sll_halen)
+        || (len < (int)(sizeof(*ah) + 2 * (4 + ah->ar_hln))))
                return false;
 
-       memcpy(&src_ip, p + ah->ar_hln, 4);
-       memcpy(&dst_ip, p + ah->ar_hln + 4 + ah->ar_hln, 4);
+       move_from_unaligned32(src_ip.s_addr, p + ah->ar_hln);
+       move_from_unaligned32(dst_ip.s_addr, p + ah->ar_hln + 4 + ah->ar_hln);
 
        if (dst.s_addr != src_ip.s_addr)
                return false;
@@ -199,7 +209,7 @@ static bool recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
                   dst_ip/dst_hw do not matter.
                 */
                if ((memcmp(p, &me.sll_addr, me.sll_halen) == 0)
-                       || (src.s_addr && src.s_addr != dst_ip.s_addr))
+                || (src.s_addr && src.s_addr != dst_ip.s_addr))
                        return false;
        }
        if (!(option_mask32 & QUIET)) {
@@ -244,7 +254,7 @@ static bool recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
 }
 
 int arping_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int arping_main(int argc ATTRIBUTE_UNUSED, char **argv)
+int arping_main(int argc UNUSED_PARAM, char **argv)
 {
        const char *device = "eth0";
        char *source = NULL;
@@ -285,7 +295,7 @@ int arping_main(int argc ATTRIBUTE_UNUSED, char **argv)
                struct ifreq ifr;
 
                memset(&ifr, 0, sizeof(ifr));
-               strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name) - 1);
+               strncpy_IFNAMSIZ(ifr.ifr_name, device);
                /* We use ifr.ifr_name in error msg so that problem
                 * with truncated name will be visible */
                ioctl_or_perror_and_die(sock_fd, SIOCGIFINDEX, &ifr, err_str, "not found");
@@ -305,7 +315,7 @@ int arping_main(int argc ATTRIBUTE_UNUSED, char **argv)
        /* if (!inet_aton(target, &dst)) - not needed */ {
                len_and_sockaddr *lsa;
                lsa = xhost_and_af2sockaddr(target, 0, AF_INET);
-               memcpy(&dst, &lsa->u.sin.sin_addr.s_addr, 4);
+               dst = lsa->u.sin.sin_addr;
                if (ENABLE_FEATURE_CLEAN_UP)
                        free(lsa);
        }
@@ -321,8 +331,7 @@ int arping_main(int argc ATTRIBUTE_UNUSED, char **argv)
                struct sockaddr_in saddr;
                int probe_fd = xsocket(AF_INET, SOCK_DGRAM, 0);
 
-               if (setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1) == -1)
-                       bb_perror_msg("cannot bind to device %s", device);
+               setsockopt_bindtodevice(probe_fd, device);
                memset(&saddr, 0, sizeof(saddr));
                saddr.sin_family = AF_INET;
                if (src.s_addr) {