--- arping.c 2010-05-31 17:21:39.000000000 +0530 +++ arping.c 2010-05-31 17:33:04.000000000 +0530 @@ -32,6 +32,8 @@ #include #include +#include + #include "SNAPSHOT.h" static void usage(void) __attribute__((noreturn)); @@ -50,8 +52,8 @@ int s; int broadcast_only; -struct sockaddr_ll me; -struct sockaddr_ll he; +struct sockaddr_storage me; +struct sockaddr_storage he; struct timeval start, last; @@ -61,6 +63,18 @@ #define MS_TDIFF(tv1,tv2) ( ((tv1).tv_sec-(tv2).tv_sec)*1000 + \ ((tv1).tv_usec-(tv2).tv_usec)/1000 ) +#define OFFSET_OF(name,ele) ((size_t)(((name *)0)->ele)) + +static inline socklen_t sll_len(size_t halen) +{ + socklen_t len = OFFSET_OF(struct sockaddr_ll, sll_addr) + halen; + if (len < sizeof(struct sockaddr_ll)) + len = sizeof(struct sockaddr_ll); + return len; +} + +#define SLL_LEN(hln) sll_len(hln) + void usage(void) { fprintf(stderr, @@ -124,7 +138,7 @@ p+=4; gettimeofday(&now, NULL); - err = sendto(s, buf, p-buf, 0, (struct sockaddr*)HE, sizeof(*HE)); + err = sendto(s, buf, p-buf, 0, (struct sockaddr*)HE, SLL_LEN(ah->ar_hln)); if (err == p-buf) { last = now; sent++; @@ -172,7 +186,8 @@ finish(); if (last.tv_sec==0 || MS_TDIFF(tv,last) > 500) { - send_pack(s, src, dst, &me, &he); + send_pack(s, src, dst, + (struct sockaddr_ll *)&me, (struct sockaddr_ll *)&he); if (count == 0 && unsolicited) finish(); } @@ -219,7 +234,7 @@ return 0; if (ah->ar_pln != 4) return 0; - if (ah->ar_hln != me.sll_halen) + if (ah->ar_hln != ((struct sockaddr_ll *)&me)->sll_halen) return 0; if (len < sizeof(*ah) + 2*(4 + ah->ar_hln)) return 0; @@ -230,7 +245,7 @@ return 0; if (src.s_addr != dst_ip.s_addr) return 0; - if (memcmp(p+ah->ar_hln+4, &me.sll_addr, ah->ar_hln)) + if (memcmp(p+ah->ar_hln+4, ((struct sockaddr_ll *)&me)->sll_addr, ah->ar_hln)) return 0; } else { /* DAD packet was: @@ -248,7 +263,7 @@ */ if (src_ip.s_addr != dst.s_addr) return 0; - if (memcmp(p, &me.sll_addr, me.sll_halen) == 0) + if (memcmp(p, ((struct sockaddr_ll *)&me)->sll_addr, ((struct sockaddr_ll *)&me)->sll_halen) == 0) return 0; if (src.s_addr && src.s_addr != dst_ip.s_addr) return 0; @@ -264,7 +279,7 @@ printf("for %s ", inet_ntoa(dst_ip)); s_printed = 1; } - if (memcmp(p+ah->ar_hln+4, me.sll_addr, ah->ar_hln)) { + if (memcmp(p+ah->ar_hln+4, ((struct sockaddr_ll *)&me)->sll_addr, ah->ar_hln)) { if (!s_printed) printf("for "); printf("["); @@ -290,12 +305,42 @@ if (quit_on_reply) finish(); if(!broadcast_only) { - memcpy(he.sll_addr, p, me.sll_halen); + memcpy(((struct sockaddr_ll *)&he)->sll_addr, p, ((struct sockaddr_ll *)&me)->sll_halen); unicasting=1; } return 1; } +void set_device_broadcast(char *device, unsigned char *ba, size_t balen) +{ + struct sysfs_class_device *dev; + struct sysfs_attribute *brdcast; + unsigned char *p; + int ch; + + dev = sysfs_open_class_device("net", device); + if (!dev) { + perror("sysfs_open_class_device(net)"); + exit(2); + } + + brdcast = sysfs_get_classdev_attr(dev, "broadcast"); + if (!brdcast) { + perror("sysfs_get_classdev_attr(broadcast)"); + exit(2); + } + + if (sysfs_read_attribute(brdcast)) { + perror("sysfs_read_attribute"); + exit(2); + } + + for (p = ba, ch = 0; p < ba + balen; p++, ch += 3) + *p++ = strtoul(brdcast->value + ch * 3, NULL, 16); + + return; +} + int main(int argc, char **argv) { @@ -456,9 +501,9 @@ close(probe_fd); }; - me.sll_family = AF_PACKET; - me.sll_ifindex = ifindex; - me.sll_protocol = htons(ETH_P_ARP); + ((struct sockaddr_ll *)&me)->sll_family = AF_PACKET; + ((struct sockaddr_ll *)&me)->sll_ifindex = ifindex; + ((struct sockaddr_ll *)&me)->sll_protocol = htons(ETH_P_ARP); if (bind(s, (struct sockaddr*)&me, sizeof(me)) == -1) { perror("bind"); exit(2); @@ -471,14 +516,20 @@ exit(2); } } - if (me.sll_halen == 0) { + if (((struct sockaddr_ll *)&me)->sll_halen == 0) { if (!quiet) printf("Interface \"%s\" is not ARPable (no ll address)\n", device); exit(dad?0:2); } he = me; - memset(he.sll_addr, -1, he.sll_halen); + +#if 1 + set_device_broadcast(device, ((struct sockaddr_ll *)&he)->sll_addr, + ((struct sockaddr_ll *)&he)->sll_halen); +#else + memset(((struct sockaddr_ll *)&he)->sll_addr, -1, ((struct sockaddr_ll *)&he)->sll_halen); +#endif if (!quiet) { printf("ARPING %s ", inet_ntoa(dst)); @@ -498,7 +549,7 @@ while(1) { sigset_t sset, osset; char packet[4096]; - struct sockaddr_ll from; + struct sockaddr_storage from; int alen = sizeof(from); int cc; @@ -507,11 +558,12 @@ perror("arping: recvfrom"); continue; } + sigemptyset(&sset); sigaddset(&sset, SIGALRM); sigaddset(&sset, SIGINT); sigprocmask(SIG_BLOCK, &sset, &osset); - recv_pack(packet, cc, &from); + recv_pack(packet, cc, (struct sockaddr_ll *)&from); sigprocmask(SIG_SETMASK, &osset, NULL); } } --- Makefile 2010-05-31 17:21:39.000000000 +0530 +++ Makefile 2010-05-31 17:23:05.000000000 +0530 @@ -41,6 +41,7 @@ tftpd: tftpd.o tftpsubs.o +arping: arping.o -lsysfs ping: ping.o ping_common.o ping6: ping6.o ping_common.o ping.o ping6.o ping_common.o: ping_common.h